Modernize Thread

- Based on C++11's `thread` and `thread_local`
- No more need to allocate-deallocate or check for null
- No pointer anymore, just a member variable
- Platform-specific implementations no longer needed (except for the few cases of non-portable functions)
- Simpler for `NO_THREADS`
- Thread ids are now the same across platforms (main is 1; others follow)
This commit is contained in:
Pedro J. Estébanez 2021-01-27 20:10:10 +01:00
parent 8f6a636ae7
commit 6d89f675b1
84 changed files with 370 additions and 1080 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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();
}
}

View file

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

View file

@ -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.wait_to_finish();
memdelete(resolver);
}

View file

@ -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

View file

@ -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 <thread>
#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

View file

@ -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;
};

View file

@ -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

View file

@ -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<Thread *> threads;
int thread_count = OS::get_singleton()->get_processor_count();
Thread *threads = memnew_arr(Thread, thread_count);
threads.resize(OS::get_singleton()->get_processor_count());
for (int i = 0; i < threads.size(); i++) {
threads.write[i] = Thread::create(process_array_thread<ThreadArrayProcessData<C, U> >, &data);
for (int i = 0; i < thread_count; i++) {
threads[i].start(process_array_thread<ThreadArrayProcessData<C, U> >, &data);
}
for (int i = 0; i < threads.size(); i++) {
Thread::wait_to_finish(threads[i]);
memdelete(threads[i]);
for (int i = 0; i < thread_count; i++) {
threads[i].wait_to_finish();
}
memdelete_arr(threads);
}
#else

View file

@ -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;
}
thread.wait_to_finish();
finish_device();
}
AudioDriverALSA::AudioDriverALSA() :
thread(NULL),
pcm_handle(NULL),
device_name("Default"),
new_device("Default") {

View file

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

View file

@ -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;
}
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;
}

View file

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

View file

@ -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),

View file

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

View file

@ -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<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM);

View file

@ -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 <pthread_np.h>
#endif
static void _thread_id_key_destr_callback(void *p_value) {
memdelete(static_cast<Thread::ID *>(p_value));
}
static pthread_key_t _create_thread_id_key() {
pthread_key_t key;
pthread_key_create(&key, &_thread_id_key_destr_callback);
return key;
}
pthread_key_t ThreadPosix::thread_id_key = _create_thread_id_key();
Thread::ID ThreadPosix::next_thread_id = 0;
Thread::ID ThreadPosix::get_id() const {
return id;
}
Thread *ThreadPosix::create_thread_posix() {
return memnew(ThreadPosix);
}
void *ThreadPosix::thread_callback(void *userdata) {
ThreadPosix *t = reinterpret_cast<ThreadPosix *>(userdata);
t->id = atomic_increment(&next_thread_id);
pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
ScriptServer::thread_enter(); //scripts may need to attach a stack
t->callback(t->user);
ScriptServer::thread_exit();
return NULL;
}
Thread *ThreadPosix::create_func_posix(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
ThreadPosix *tr = memnew(ThreadPosix);
tr->callback = p_callback;
tr->user = p_user;
pthread_attr_init(&tr->pthread_attr);
pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
pthread_attr_setstacksize(&tr->pthread_attr, 256 * 1024);
pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
return tr;
}
Thread::ID ThreadPosix::get_thread_id_func_posix() {
void *value = pthread_getspecific(thread_id_key);
if (value)
return *static_cast<ID *>(value);
ID new_id = atomic_increment(&next_thread_id);
pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
return new_id;
}
void ThreadPosix::wait_to_finish_func_posix(Thread *p_thread) {
ThreadPosix *tp = static_cast<ThreadPosix *>(p_thread);
ERR_FAIL_COND(!tp);
ERR_FAIL_COND(tp->pthread == 0);
pthread_join(tp->pthread, NULL);
tp->pthread = 0;
}
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

View file

@ -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 <pthread.h>
#include <sys/types.h>
class ThreadPosix : public Thread {
static pthread_key_t thread_id_key;
static ID next_thread_id;
pthread_t pthread;
pthread_attr_t pthread_attr;
ThreadCreateCallback callback;
void *user;
ID id;
static Thread *create_thread_posix();
static void *thread_callback(void *userdata);
static Thread *create_func_posix(ThreadCreateCallback p_callback, void *, const Settings &);
static ID get_thread_id_func_posix();
static void wait_to_finish_func_posix(Thread *p_thread);
static Error set_name_func_posix(const String &p_name);
ThreadPosix();
public:
virtual ID get_id() const;
static void make_default();
~ThreadPosix();
};
#if !defined(NO_THREADS)
void init_thread_posix();
#endif
#endif

View file

@ -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;
}
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;

View file

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

View file

@ -1,100 +0,0 @@
/*************************************************************************/
/* thread_windows.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "thread_windows.h"
#if defined(WINDOWS_ENABLED) && !defined(UWP_ENABLED)
#include "core/os/memory.h"
Thread::ID ThreadWindows::get_id() const {
return id;
}
Thread *ThreadWindows::create_thread_windows() {
return memnew(ThreadWindows);
}
DWORD ThreadWindows::thread_callback(LPVOID userdata) {
ThreadWindows *t = reinterpret_cast<ThreadWindows *>(userdata);
ScriptServer::thread_enter(); //scripts may need to attach a stack
t->id = (ID)GetCurrentThreadId(); // must implement
t->callback(t->user);
SetEvent(t->handle);
ScriptServer::thread_exit();
return 0;
}
Thread *ThreadWindows::create_func_windows(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
ThreadWindows *tr = memnew(ThreadWindows);
tr->callback = p_callback;
tr->user = p_user;
tr->handle = CreateEvent(NULL, TRUE, FALSE, NULL);
QueueUserWorkItem(thread_callback, tr, WT_EXECUTELONGFUNCTION);
return tr;
}
Thread::ID ThreadWindows::get_thread_id_func_windows() {
return (ID)GetCurrentThreadId(); //must implement
}
void ThreadWindows::wait_to_finish_func_windows(Thread *p_thread) {
ThreadWindows *tp = static_cast<ThreadWindows *>(p_thread);
ERR_FAIL_COND(!tp);
WaitForSingleObject(tp->handle, INFINITE);
CloseHandle(tp->handle);
//`memdelete(tp);
}
void ThreadWindows::make_default() {
create_func = create_func_windows;
get_thread_id_func = get_thread_id_func_windows;
wait_to_finish_func = wait_to_finish_func_windows;
}
ThreadWindows::ThreadWindows() :
handle(NULL) {
}
ThreadWindows::~ThreadWindows() {
}
#endif

View file

@ -1,68 +0,0 @@
/*************************************************************************/
/* thread_windows.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef THREAD_WINDOWS_H
#define THREAD_WINDOWS_H
#ifdef WINDOWS_ENABLED
#include "core/os/thread.h"
#include "core/script_language.h"
#include <windows.h>
class ThreadWindows : public Thread {
ThreadCreateCallback callback;
void *user;
ID id;
HANDLE handle;
static Thread *create_thread_windows();
static DWORD WINAPI thread_callback(LPVOID userdata);
static Thread *create_func_windows(ThreadCreateCallback p_callback, void *, const Settings &);
static ID get_thread_id_func_windows();
static void wait_to_finish_func_windows(Thread *p_thread);
ThreadWindows();
public:
virtual ID get_id() const;
static void make_default();
~ThreadWindows();
};
#endif
#endif

View file

@ -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++) {

View file

@ -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;

View file

@ -199,8 +199,10 @@ Ref<AudioStreamPreview> 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<ObjectID, Preview>::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

View file

@ -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<String> *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;

View file

@ -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;

View file

@ -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) {

View file

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

View file

@ -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;

View file

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

View file

@ -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();
}

View file

@ -49,7 +49,7 @@ class EditorFileServer : public Object {
struct ClientData {
Thread *thread;
Thread thread;
Ref<StreamPeerTCP> connection;
Map<int, FileAccess *> 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;

View file

@ -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) {

View file

@ -267,12 +267,13 @@ void image_compress_cvtt(Image *p_image, float p_lossy_quality, Image::CompressS
job_queue.num_tasks = static_cast<uint32_t>(tasks.size());
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]);
}
}

View file

@ -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

View file

@ -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;

View file

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

View file

@ -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;

View file

@ -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<jclass> 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<jclass> 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<jstring> 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<jclass> timeZoneClass(env, env->FindClass("java/util/TimeZone"));
ERR_FAIL_NULL_V(timeZoneClass, NULL);

View file

@ -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<Image> &p_image) {
void NoiseTexture::_thread_done(const Ref<Image> &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;

View file

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

View file

@ -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;

View file

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

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -272,7 +272,7 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
Vector<Device> 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();
}
};

View file

@ -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<MethodInfo>::Element *E = M->get().front(); E; E = E->next()) {
@ -1048,7 +1048,7 @@ Ref<JavaClass> JavaClassWrapper::wrap(const String &p_class) {
if (class_cache.has(p_class))
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<JavaClass>());
@ -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;");

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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<String> GodotJavaWrapper::get_granted_permissions() const {
Vector<String> 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<jobjectArray *>(&permissions_object);
@ -250,14 +250,14 @@ Vector<String> 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);
}
}

View file

@ -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);
}
}

View file

@ -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) {

View file

@ -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<Thread::ID *>(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;
}
pthread_key_t ThreadAndroid::thread_id_key = _create_thread_id_key();
Thread::ID ThreadAndroid::next_thread_id = 0;
Thread::ID ThreadAndroid::get_id() const {
return id;
}
Thread *ThreadAndroid::create_thread_jandroid() {
return memnew(ThreadAndroid);
}
void *ThreadAndroid::thread_callback(void *userdata) {
ThreadAndroid *t = reinterpret_cast<ThreadAndroid *>(userdata);
setup_thread();
ScriptServer::thread_enter(); //scripts may need to attach a stack
t->id = atomic_increment(&next_thread_id);
pthread_setspecific(thread_id_key, (void *)memnew(ID(t->id)));
t->callback(t->user);
ScriptServer::thread_exit();
return NULL;
}
Thread *ThreadAndroid::create_func_jandroid(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
ThreadAndroid *tr = memnew(ThreadAndroid);
tr->callback = p_callback;
tr->user = p_user;
pthread_attr_init(&tr->pthread_attr);
pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr);
return tr;
}
Thread::ID ThreadAndroid::get_thread_id_func_jandroid() {
void *value = pthread_getspecific(thread_id_key);
if (value)
return *static_cast<ID *>(value);
ID new_id = atomic_increment(&next_thread_id);
pthread_setspecific(thread_id_key, (void *)memnew(ID(new_id)));
return new_id;
}
void ThreadAndroid::wait_to_finish_func_jandroid(Thread *p_thread) {
ThreadAndroid *tp = static_cast<ThreadAndroid *>(p_thread);
ERR_FAIL_COND(!tp);
ERR_FAIL_COND(tp->pthread == 0);
pthread_join(tp->pthread, NULL);
tp->pthread = 0;
}
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) {
static void term_thread() {
java_vm->DetachCurrentThread();
pthread_setspecific(jvm_key, NULL);
}
}
pthread_key_t ThreadAndroid::jvm_key;
JavaVM *ThreadAndroid::java_vm = NULL;
void ThreadAndroid::setup_thread() {
if (pthread_getspecific(jvm_key))
return; //already setup
JNIEnv *env;
java_vm->AttachCurrentThread(&env, NULL);
pthread_setspecific(jvm_key, (void *)env);
void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env) {
java_vm = p_jvm;
env = p_env;
Thread::_set_platform_funcs(nullptr, nullptr, &init_thread, &term_thread);
}
void ThreadAndroid::make_default(JavaVM *p_java_vm) {
java_vm = p_java_vm;
create_func = create_func_jandroid;
get_thread_id_func = get_thread_id_func_jandroid;
wait_to_finish_func = wait_to_finish_func_jandroid;
pthread_key_create(&jvm_key, _thread_destroyed);
setup_thread();
void setup_android_thread() {
init_thread();
}
JNIEnv *ThreadAndroid::get_env() {
if (!pthread_getspecific(jvm_key)) {
setup_thread();
}
JNIEnv *env = NULL;
java_vm->AttachCurrentThread(&env, NULL);
JNIEnv *get_jni_env() {
return env;
}
ThreadAndroid::ThreadAndroid() {
pthread = 0;
}
ThreadAndroid::~ThreadAndroid() {
}

View file

@ -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 <jni.h>
#include <pthread.h>
#include <sys/types.h>
class ThreadAndroid : public Thread {
void init_thread_jandroid(JavaVM *p_jvm, JNIEnv *p_env);
static pthread_key_t thread_id_key;
static ID next_thread_id;
pthread_t pthread;
pthread_attr_t pthread_attr;
ThreadCreateCallback callback;
void *user;
ID id;
static Thread *create_thread_jandroid();
static void *thread_callback(void *userdata);
static Thread *create_func_jandroid(ThreadCreateCallback p_callback, void *, const Settings &);
static ID get_thread_id_func_jandroid();
static void wait_to_finish_func_jandroid(Thread *p_thread);
static void _thread_destroyed(void *value);
ThreadAndroid();
static pthread_key_t jvm_key;
static JavaVM *java_vm;
public:
virtual ID get_id() const;
static void make_default(JavaVM *p_java_vm);
static void setup_thread();
static JNIEnv *get_env();
~ThreadAndroid();
};
void setup_android_thread();
JNIEnv *get_jni_env();
#endif

View file

@ -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<PluginConfigIOS> 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() {

View file

@ -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

View file

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

View file

@ -213,7 +213,7 @@ class EditorExportPlatformJavaScript : public EditorExportPlatform {
Ref<EditorHTTPServer> 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<Image> 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() {

View file

@ -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 <ppltasks.h>
#include <wrl.h>
@ -137,8 +136,6 @@ void OS_UWP::initialize_core() {
//RedirectIOToConsole();
ThreadUWP::make_default();
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);

View file

@ -1,73 +0,0 @@
/*************************************************************************/
/* thread_uwp.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "thread_uwp.h"
#include "core/os/memory.h"
Thread *ThreadUWP::create_func_uwp(ThreadCreateCallback p_callback, void *p_user, const Settings &) {
ThreadUWP *thread = memnew(ThreadUWP);
std::thread new_thread(p_callback, p_user);
std::swap(thread->thread, new_thread);
return thread;
};
Thread::ID ThreadUWP::get_thread_id_func_uwp() {
return std::hash<std::thread::id>()(std::this_thread::get_id());
};
void ThreadUWP::wait_to_finish_func_uwp(Thread *p_thread) {
ThreadUWP *tp = static_cast<ThreadUWP *>(p_thread);
tp->thread.join();
};
Thread::ID ThreadUWP::get_id() const {
return std::hash<std::thread::id>()(thread.get_id());
};
void ThreadUWP::make_default() {
create_func = create_func_uwp;
get_thread_id_func = get_thread_id_func_uwp;
wait_to_finish_func = wait_to_finish_func_uwp;
};
ThreadUWP::ThreadUWP(){
};
ThreadUWP::~ThreadUWP(){
};

View file

@ -1,60 +0,0 @@
/*************************************************************************/
/* thread_uwp.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef THREAD_UWP_H
#define THREAD_UWP_H
#ifdef UWP_ENABLED
#include "core/os/thread.h"
#include <thread>
class ThreadUWP : public Thread {
std::thread thread;
static Thread *create_func_uwp(ThreadCreateCallback p_callback, void *, const Settings &);
static ID get_thread_id_func_uwp();
static void wait_to_finish_func_uwp(Thread *p_thread);
ThreadUWP();
public:
virtual ID get_id() const;
static void make_default();
~ThreadUWP();
};
#endif
#endif

View file

@ -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<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);

View file

@ -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();
}

View file

@ -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<String> attached_devices;

View file

@ -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);

View file

@ -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<XEvent> polled_events;
static void _poll_events_thread(void *ud);

View file

@ -113,7 +113,7 @@ Error HTTPRequest::request(const String &p_url, const Vector<String> &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;

View file

@ -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);

View file

@ -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<Image> &p_image) {
VS::get_singleton()->texture_allocate(texture, panorama->get_width(), panorama->get_height(), 0, Image::FORMAT_RGBE9995, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
VS::get_singleton()->texture_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);

View file

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

View file

@ -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(){
thread = NULL;
};
AudioDriverDummy::~AudioDriverDummy(){

View file

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

View file

@ -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
}

View file

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

View file

@ -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;

View file

@ -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;

View file

@ -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();
}

View file

@ -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<Instance *> probe_bake_list;

View file

@ -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");

View file

@ -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;