Merge pull request #66803 from akien-mga/core-remove-NO_THREADS
Remove `NO_THREADS` fallback code, Godot 4 requires thread support
This commit is contained in:
commit
d598fff7c2
29 changed files with 13 additions and 561 deletions
|
@ -429,10 +429,6 @@ void OS::delay_msec(int p_msec) const {
|
||||||
::OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000);
|
::OS::get_singleton()->delay_usec(int64_t(p_msec) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OS::can_use_threads() const {
|
|
||||||
return ::OS::get_singleton()->can_use_threads();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OS::is_userfs_persistent() const {
|
bool OS::is_userfs_persistent() const {
|
||||||
return ::OS::get_singleton()->is_userfs_persistent();
|
return ::OS::get_singleton()->is_userfs_persistent();
|
||||||
}
|
}
|
||||||
|
@ -566,8 +562,6 @@ void OS::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &OS::is_userfs_persistent);
|
ClassDB::bind_method(D_METHOD("is_userfs_persistent"), &OS::is_userfs_persistent);
|
||||||
ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &OS::is_stdout_verbose);
|
ClassDB::bind_method(D_METHOD("is_stdout_verbose"), &OS::is_stdout_verbose);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("can_use_threads"), &OS::can_use_threads);
|
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("is_debug_build"), &OS::is_debug_build);
|
ClassDB::bind_method(D_METHOD("is_debug_build"), &OS::is_debug_build);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &OS::get_static_memory_usage);
|
ClassDB::bind_method(D_METHOD("get_static_memory_usage"), &OS::get_static_memory_usage);
|
||||||
|
|
|
@ -219,8 +219,6 @@ public:
|
||||||
uint64_t get_ticks_msec() const;
|
uint64_t get_ticks_msec() const;
|
||||||
uint64_t get_ticks_usec() const;
|
uint64_t get_ticks_usec() const;
|
||||||
|
|
||||||
bool can_use_threads() const;
|
|
||||||
|
|
||||||
bool is_userfs_persistent() const;
|
bool is_userfs_persistent() const;
|
||||||
|
|
||||||
bool is_stdout_verbose() const;
|
bool is_stdout_verbose() const;
|
||||||
|
|
|
@ -79,10 +79,8 @@ RemoteDebuggerPeerTCP::RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_tcp) {
|
||||||
tcp_client = p_tcp;
|
tcp_client = p_tcp;
|
||||||
if (tcp_client.is_valid()) { // Attaching to an already connected stream.
|
if (tcp_client.is_valid()) { // Attaching to an already connected stream.
|
||||||
connected = true;
|
connected = true;
|
||||||
#ifndef NO_THREADS
|
|
||||||
running = true;
|
running = true;
|
||||||
thread.start(_thread_func, this);
|
thread.start(_thread_func, this);
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
tcp_client.instantiate();
|
tcp_client.instantiate();
|
||||||
}
|
}
|
||||||
|
@ -183,10 +181,8 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
connected = true;
|
connected = true;
|
||||||
#ifndef NO_THREADS
|
|
||||||
running = true;
|
running = true;
|
||||||
thread.start(_thread_func, this);
|
thread.start(_thread_func, this);
|
||||||
#endif
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,9 +204,7 @@ void RemoteDebuggerPeerTCP::_thread_func(void *p_ud) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteDebuggerPeerTCP::poll() {
|
void RemoteDebuggerPeerTCP::poll() {
|
||||||
#ifdef NO_THREADS
|
// Nothing to do, polling is done in thread.
|
||||||
_poll();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteDebuggerPeerTCP::_poll() {
|
void RemoteDebuggerPeerTCP::_poll() {
|
||||||
|
|
|
@ -43,12 +43,12 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool is_peer_connected() = 0;
|
virtual bool is_peer_connected() = 0;
|
||||||
|
virtual int get_max_message_size() const = 0;
|
||||||
virtual bool has_message() = 0;
|
virtual bool has_message() = 0;
|
||||||
virtual Error put_message(const Array &p_arr) = 0;
|
virtual Error put_message(const Array &p_arr) = 0;
|
||||||
virtual Array get_message() = 0;
|
virtual Array get_message() = 0;
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
virtual void poll() = 0;
|
virtual void poll() = 0;
|
||||||
virtual int get_max_message_size() const = 0;
|
|
||||||
virtual bool can_block() const { return true; } // If blocking io is allowed on main thread (debug).
|
virtual bool can_block() const { return true; } // If blocking io is allowed on main thread (debug).
|
||||||
|
|
||||||
RemoteDebuggerPeer();
|
RemoteDebuggerPeer();
|
||||||
|
@ -81,12 +81,12 @@ public:
|
||||||
|
|
||||||
Error connect_to_host(const String &p_host, uint16_t p_port);
|
Error connect_to_host(const String &p_host, uint16_t p_port);
|
||||||
|
|
||||||
void poll() override;
|
|
||||||
bool is_peer_connected() override;
|
bool is_peer_connected() override;
|
||||||
bool has_message() override;
|
|
||||||
Array get_message() override;
|
|
||||||
Error put_message(const Array &p_arr) override;
|
|
||||||
int get_max_message_size() const override;
|
int get_max_message_size() const override;
|
||||||
|
bool has_message() override;
|
||||||
|
Error put_message(const Array &p_arr) override;
|
||||||
|
Array get_message() override;
|
||||||
|
void poll() override;
|
||||||
void close() override;
|
void close() override;
|
||||||
|
|
||||||
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
|
RemoteDebuggerPeerTCP(Ref<StreamPeerTCP> p_stream = Ref<StreamPeerTCP>());
|
||||||
|
|
|
@ -40,11 +40,7 @@ void _global_unlock() {
|
||||||
_global_mutex.unlock();
|
_global_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_THREADS
|
|
||||||
|
|
||||||
template class MutexImpl<std::recursive_mutex>;
|
template class MutexImpl<std::recursive_mutex>;
|
||||||
template class MutexImpl<std::mutex>;
|
template class MutexImpl<std::mutex>;
|
||||||
template class MutexLock<MutexImpl<std::recursive_mutex>>;
|
template class MutexLock<MutexImpl<std::recursive_mutex>>;
|
||||||
template class MutexLock<MutexImpl<std::mutex>>;
|
template class MutexLock<MutexImpl<std::mutex>>;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
#include "core/error/error_list.h"
|
#include "core/error/error_list.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
template <class StdMutexT>
|
template <class StdMutexT>
|
||||||
|
@ -79,29 +77,4 @@ extern template class MutexImpl<std::mutex>;
|
||||||
extern template class MutexLock<MutexImpl<std::recursive_mutex>>;
|
extern template class MutexLock<MutexImpl<std::recursive_mutex>>;
|
||||||
extern template class MutexLock<MutexImpl<std::mutex>>;
|
extern template class MutexLock<MutexImpl<std::mutex>>;
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class FakeMutex {
|
|
||||||
FakeMutex() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class MutexT>
|
|
||||||
class MutexImpl {
|
|
||||||
public:
|
|
||||||
_ALWAYS_INLINE_ void lock() const {}
|
|
||||||
_ALWAYS_INLINE_ void unlock() const {}
|
|
||||||
_ALWAYS_INLINE_ Error try_lock() const { return OK; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class MutexT>
|
|
||||||
class MutexLock {
|
|
||||||
public:
|
|
||||||
explicit MutexLock(const MutexT &p_mutex) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
using Mutex = MutexImpl<FakeMutex>;
|
|
||||||
using BinaryMutex = MutexImpl<FakeMutex>; // Non-recursive, handle with care
|
|
||||||
|
|
||||||
#endif // !NO_THREADS
|
|
||||||
|
|
||||||
#endif // MUTEX_H
|
#endif // MUTEX_H
|
||||||
|
|
|
@ -328,14 +328,6 @@ String OS::get_processor_name() const {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OS::can_use_threads() const {
|
|
||||||
#ifdef NO_THREADS
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) {
|
void OS::set_has_server_feature_callback(HasServerFeatureCallback p_callback) {
|
||||||
has_server_feature_callback = p_callback;
|
has_server_feature_callback = p_callback;
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,8 +299,6 @@ public:
|
||||||
|
|
||||||
virtual String get_unique_id() const;
|
virtual String get_unique_id() const;
|
||||||
|
|
||||||
virtual bool can_use_threads() const;
|
|
||||||
|
|
||||||
bool has_feature(const String &p_feature);
|
bool has_feature(const String &p_feature);
|
||||||
|
|
||||||
void set_has_server_feature_callback(HasServerFeatureCallback p_callback);
|
void set_has_server_feature_callback(HasServerFeatureCallback p_callback);
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
|
|
||||||
#include "core/error/error_list.h"
|
#include "core/error/error_list.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
|
|
||||||
class RWLock {
|
class RWLock {
|
||||||
|
@ -72,21 +70,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class RWLock {
|
|
||||||
public:
|
|
||||||
void read_lock() const {}
|
|
||||||
void read_unlock() const {}
|
|
||||||
Error read_try_lock() const { return OK; }
|
|
||||||
|
|
||||||
void write_lock() {}
|
|
||||||
void write_unlock() {}
|
|
||||||
Error write_try_lock() { return OK; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class RWLockRead {
|
class RWLockRead {
|
||||||
const RWLock &lock;
|
const RWLock &lock;
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,6 @@
|
||||||
#include "core/error/error_list.h"
|
#include "core/error/error_list.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
@ -70,15 +68,4 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
class Semaphore {
|
|
||||||
public:
|
|
||||||
_ALWAYS_INLINE_ void post() const {}
|
|
||||||
_ALWAYS_INLINE_ void wait() const {}
|
|
||||||
_ALWAYS_INLINE_ bool try_wait() const { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SEMAPHORE_H
|
#endif // SEMAPHORE_H
|
||||||
|
|
|
@ -34,9 +34,6 @@
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
#include "core/object/script_language.h"
|
#include "core/object/script_language.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#include "core/templates/safe_refcount.h"
|
#include "core/templates/safe_refcount.h"
|
||||||
|
|
||||||
Error (*Thread::set_name_func)(const String &) = nullptr;
|
Error (*Thread::set_name_func)(const String &) = nullptr;
|
||||||
|
@ -128,5 +125,4 @@ Thread::~Thread() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
#endif // PLATFORM_THREAD_OVERRIDE
|
#endif // PLATFORM_THREAD_OVERRIDE
|
||||||
|
|
|
@ -35,15 +35,14 @@
|
||||||
#ifdef PLATFORM_THREAD_OVERRIDE
|
#ifdef PLATFORM_THREAD_OVERRIDE
|
||||||
#include "platform_thread.h"
|
#include "platform_thread.h"
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifndef THREAD_H
|
#ifndef THREAD_H
|
||||||
#define THREAD_H
|
#define THREAD_H
|
||||||
|
|
||||||
|
#include "core/templates/safe_refcount.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
#include "core/templates/safe_refcount.h"
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#endif
|
|
||||||
|
|
||||||
class String;
|
class String;
|
||||||
|
|
||||||
|
@ -65,7 +64,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
friend class Main;
|
friend class Main;
|
||||||
|
|
||||||
static ID main_thread_id;
|
static ID main_thread_id;
|
||||||
|
@ -82,7 +80,6 @@ private:
|
||||||
static void (*set_priority_func)(Thread::Priority);
|
static void (*set_priority_func)(Thread::Priority);
|
||||||
static void (*init_func)();
|
static void (*init_func)();
|
||||||
static void (*term_func)();
|
static void (*term_func)();
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void _set_platform_funcs(
|
static void _set_platform_funcs(
|
||||||
|
@ -91,7 +88,6 @@ public:
|
||||||
void (*p_init_func)() = nullptr,
|
void (*p_init_func)() = nullptr,
|
||||||
void (*p_term_func)() = nullptr);
|
void (*p_term_func)() = nullptr);
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
_FORCE_INLINE_ ID get_id() const { return id; }
|
_FORCE_INLINE_ ID get_id() const { return id; }
|
||||||
// get the ID of the caller thread
|
// get the ID of the caller thread
|
||||||
_FORCE_INLINE_ static ID get_caller_id() { return caller_id; }
|
_FORCE_INLINE_ static ID get_caller_id() { return caller_id; }
|
||||||
|
@ -107,19 +103,6 @@ public:
|
||||||
|
|
||||||
Thread();
|
Thread();
|
||||||
~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 // THREAD_H
|
#endif // THREAD_H
|
||||||
|
|
|
@ -49,8 +49,6 @@ struct ThreadArrayProcessData {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef NO_THREADS
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void process_array_thread(void *ud) {
|
void process_array_thread(void *ud) {
|
||||||
T &data = *(T *)ud;
|
T &data = *(T *)ud;
|
||||||
|
@ -86,21 +84,4 @@ void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_us
|
||||||
memdelete_arr(threads);
|
memdelete_arr(threads);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <class C, class M, class U>
|
|
||||||
void thread_process_array(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) {
|
|
||||||
ThreadArrayProcessData<C, U> data;
|
|
||||||
data.method = p_method;
|
|
||||||
data.instance = p_instance;
|
|
||||||
data.userdata = p_userdata;
|
|
||||||
data.index.set(0);
|
|
||||||
data.elements = p_elements;
|
|
||||||
for (uint32_t i = 0; i < p_elements; i++) {
|
|
||||||
data.process(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // THREADED_ARRAY_PROCESSOR_H
|
#endif // THREADED_ARRAY_PROCESSOR_H
|
||||||
|
|
|
@ -46,9 +46,7 @@ class CharString;
|
||||||
template <class T, class V>
|
template <class T, class V>
|
||||||
class VMap;
|
class VMap;
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t)
|
SAFE_NUMERIC_TYPE_PUN_GUARANTEES(uint32_t)
|
||||||
#endif
|
|
||||||
|
|
||||||
// Silence a false positive warning (see GH-52119).
|
// Silence a false positive warning (see GH-52119).
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
|
|
@ -33,11 +33,9 @@
|
||||||
|
|
||||||
#include "core/os/memory.h"
|
#include "core/os/memory.h"
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <functional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
// Design goals for these classes:
|
// Design goals for these classes:
|
||||||
|
@ -239,159 +237,4 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // NO_THREADS
|
|
||||||
|
|
||||||
// Effectively the same structure without the atomics. It's probably possible to simplify it but the semantics shouldn't differ greatly.
|
|
||||||
template <class T, class A = DefaultAllocator>
|
|
||||||
class SafeList {
|
|
||||||
struct SafeListNode {
|
|
||||||
SafeListNode *next = nullptr;
|
|
||||||
|
|
||||||
// If the node is logically deleted, this pointer will typically point to the previous list item in time that was also logically deleted.
|
|
||||||
SafeListNode *graveyard_next = nullptr;
|
|
||||||
|
|
||||||
std::function<void(T)> deletion_fn = [](T t) { return; };
|
|
||||||
|
|
||||||
T val;
|
|
||||||
};
|
|
||||||
|
|
||||||
SafeListNode *head = nullptr;
|
|
||||||
SafeListNode *graveyard_head = nullptr;
|
|
||||||
|
|
||||||
unsigned int active_iterator_count = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
class Iterator {
|
|
||||||
friend class SafeList;
|
|
||||||
|
|
||||||
SafeListNode *cursor = nullptr;
|
|
||||||
SafeList *list = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Iterator(SafeListNode *p_cursor, SafeList *p_list) :
|
|
||||||
cursor(p_cursor), list(p_list) {
|
|
||||||
list->active_iterator_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Iterator() {
|
|
||||||
list->active_iterator_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
T &operator*() {
|
|
||||||
return cursor->val;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator &operator++() {
|
|
||||||
cursor = cursor->next;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These two operators are mostly useful for comparisons to nullptr.
|
|
||||||
bool operator==(const void *p_other) const {
|
|
||||||
return cursor == p_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const void *p_other) const {
|
|
||||||
return cursor != p_other;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These two allow easy range-based for loops.
|
|
||||||
bool operator==(const Iterator &p_other) const {
|
|
||||||
return cursor == p_other.cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const Iterator &p_other) const {
|
|
||||||
return cursor != p_other.cursor;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Calling this will cause an allocation.
|
|
||||||
void insert(T p_value) {
|
|
||||||
SafeListNode *new_node = memnew_allocator(SafeListNode, A);
|
|
||||||
new_node->val = p_value;
|
|
||||||
new_node->next = head;
|
|
||||||
head = new_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator find(T p_value) {
|
|
||||||
for (Iterator it = begin(); it != end(); ++it) {
|
|
||||||
if (*it == p_value) {
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase(T p_value, std::function<void(T)> p_deletion_fn) {
|
|
||||||
erase(find(p_value), p_deletion_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase(T p_value) {
|
|
||||||
erase(find(p_value), [](T t) { return; });
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase(Iterator p_iterator, std::function<void(T)> p_deletion_fn) {
|
|
||||||
p_iterator.cursor->deletion_fn = p_deletion_fn;
|
|
||||||
erase(p_iterator);
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase(Iterator p_iterator) {
|
|
||||||
Iterator prev = begin();
|
|
||||||
for (; prev != end(); ++prev) {
|
|
||||||
if (prev.cursor && prev.cursor->next == p_iterator.cursor) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (prev == end()) {
|
|
||||||
// Not in the list, nothing to do.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// First, remove the node from the list.
|
|
||||||
prev.cursor->next = p_iterator.cursor->next;
|
|
||||||
|
|
||||||
// Then queue it for deletion by putting it in the node graveyard. Don't touch `next` because an iterator might still be pointing at this node.
|
|
||||||
p_iterator.cursor->graveyard_next = graveyard_head;
|
|
||||||
graveyard_head = p_iterator.cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator begin() {
|
|
||||||
return Iterator(head, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator end() {
|
|
||||||
return Iterator(nullptr, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calling this will cause zero to many deallocations.
|
|
||||||
bool maybe_cleanup() {
|
|
||||||
SafeListNode *cursor = graveyard_head;
|
|
||||||
if (active_iterator_count != 0) {
|
|
||||||
// It's not safe to clean up with an active iterator, because that iterator could be pointing to an element that we want to delete.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
graveyard_head = nullptr;
|
|
||||||
// Our graveyard list is now unreachable by any active iterators, detached from the main graveyard head and ready for deletion.
|
|
||||||
while (cursor) {
|
|
||||||
SafeListNode *tmp = cursor;
|
|
||||||
cursor = cursor->next;
|
|
||||||
tmp->deletion_fn(tmp->val);
|
|
||||||
memdelete_allocator<SafeListNode, A>(tmp);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
~SafeList() {
|
|
||||||
#ifdef DEBUG_ENABLED
|
|
||||||
if (!maybe_cleanup()) {
|
|
||||||
ERR_PRINT("There are still iterators around when destructing a SafeList. Memory will be leaked. This is a bug.");
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
maybe_cleanup();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SAFE_LIST_H
|
#endif // SAFE_LIST_H
|
||||||
|
|
|
@ -33,8 +33,6 @@
|
||||||
|
|
||||||
#include "core/typedefs.h"
|
#include "core/typedefs.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
@ -191,141 +189,4 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
class SafeNumeric {
|
|
||||||
protected:
|
|
||||||
T value;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_ALWAYS_INLINE_ void set(T p_value) {
|
|
||||||
value = p_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T get() const {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T increment() {
|
|
||||||
return ++value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T postincrement() {
|
|
||||||
return value++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T decrement() {
|
|
||||||
return --value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T postdecrement() {
|
|
||||||
return value--;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T add(T p_value) {
|
|
||||||
return value += p_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T postadd(T p_value) {
|
|
||||||
T old = value;
|
|
||||||
value += p_value;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T sub(T p_value) {
|
|
||||||
return value -= p_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T postsub(T p_value) {
|
|
||||||
T old = value;
|
|
||||||
value -= p_value;
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T exchange_if_greater(T p_value) {
|
|
||||||
if (value < p_value) {
|
|
||||||
value = p_value;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ T conditional_increment() {
|
|
||||||
if (value == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return ++value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ explicit SafeNumeric<T>(T p_value = static_cast<T>(0)) :
|
|
||||||
value(p_value) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SafeFlag {
|
|
||||||
protected:
|
|
||||||
bool flag;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_ALWAYS_INLINE_ bool is_set() const {
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ void set() {
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ void clear() {
|
|
||||||
flag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ void set_to(bool p_value) {
|
|
||||||
flag = p_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ explicit SafeFlag(bool p_value = false) :
|
|
||||||
flag(p_value) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SafeRefCount {
|
|
||||||
uint32_t count = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
_ALWAYS_INLINE_ bool ref() { // true on success
|
|
||||||
if (count != 0) {
|
|
||||||
++count;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ uint32_t refval() { // none-zero on success
|
|
||||||
if (count != 0) {
|
|
||||||
return ++count;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ bool unref() { // true if must be disposed of
|
|
||||||
return --count == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of
|
|
||||||
return --count;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ uint32_t get() const {
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ALWAYS_INLINE_ void init(uint32_t p_value = 1) {
|
|
||||||
count = p_value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SAFE_REFCOUNT_H
|
#endif // SAFE_REFCOUNT_H
|
||||||
|
|
|
@ -18,12 +18,6 @@
|
||||||
Displays a modal dialog box using the host OS' facilities. Execution is blocked until the dialog is closed.
|
Displays a modal dialog box using the host OS' facilities. Execution is blocked until the dialog is closed.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="can_use_threads" qualifiers="const">
|
|
||||||
<return type="bool" />
|
|
||||||
<description>
|
|
||||||
Returns [code]true[/code] if the current host platform is using multiple threads.
|
|
||||||
</description>
|
|
||||||
</method>
|
|
||||||
<method name="close_midi_inputs">
|
<method name="close_midi_inputs">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -126,9 +126,7 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OS_Unix::initialize_core() {
|
void OS_Unix::initialize_core() {
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
init_thread_posix();
|
init_thread_posix();
|
||||||
#endif
|
|
||||||
|
|
||||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
|
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES);
|
||||||
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
|
FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#if (defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)) && !defined(NO_THREADS)
|
#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED)
|
||||||
|
|
||||||
#include "thread_posix.h"
|
#include "thread_posix.h"
|
||||||
|
|
||||||
|
@ -73,4 +73,4 @@ void init_thread_posix() {
|
||||||
Thread::_set_platform_funcs(&set_name, nullptr);
|
Thread::_set_platform_funcs(&set_name, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // UNIX_ENABLED || PTHREAD_ENABLED
|
||||||
|
|
|
@ -31,8 +31,6 @@
|
||||||
#ifndef THREAD_POSIX_H
|
#ifndef THREAD_POSIX_H
|
||||||
#define THREAD_POSIX_H
|
#define THREAD_POSIX_H
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
void init_thread_posix();
|
void init_thread_posix();
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // THREAD_POSIX_H
|
#endif // THREAD_POSIX_H
|
||||||
|
|
|
@ -1706,13 +1706,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rtm >= 0 && rtm < 3) {
|
if (rtm >= 0 && rtm < 3) {
|
||||||
#ifdef NO_THREADS
|
|
||||||
rtm = OS::RENDER_THREAD_UNSAFE; // No threads available on this platform.
|
|
||||||
#else
|
|
||||||
if (editor) {
|
if (editor) {
|
||||||
rtm = OS::RENDER_THREAD_SAFE;
|
rtm = OS::RENDER_THREAD_SAFE;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
OS::get_singleton()->_render_thread_mode = OS::RenderThreadMode(rtm);
|
OS::get_singleton()->_render_thread_mode = OS::RenderThreadMode(rtm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1932,11 +1928,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||||
// Print engine name and version
|
// Print engine name and version
|
||||||
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
|
print_line(String(VERSION_NAME) + " v" + get_full_version_string() + " - " + String(VERSION_WEBSITE));
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
if (p_main_tid_override) {
|
if (p_main_tid_override) {
|
||||||
Thread::main_thread_id = p_main_tid_override;
|
Thread::main_thread_id = p_main_tid_override;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
if (editor || project_manager || cmdline_tool) {
|
if (editor || project_manager || cmdline_tool) {
|
||||||
|
|
|
@ -197,9 +197,6 @@ void NoiseTexture2D::_update_texture() {
|
||||||
use_thread = false;
|
use_thread = false;
|
||||||
first_time = false;
|
first_time = false;
|
||||||
}
|
}
|
||||||
#ifdef NO_THREADS
|
|
||||||
use_thread = false;
|
|
||||||
#endif
|
|
||||||
if (use_thread) {
|
if (use_thread) {
|
||||||
if (!noise_thread.is_started()) {
|
if (!noise_thread.is_started()) {
|
||||||
noise_thread.start(_thread_function, this);
|
noise_thread.start(_thread_function, this);
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
static RemoteDebuggerPeer *create(const String &p_uri);
|
static RemoteDebuggerPeer *create(const String &p_uri);
|
||||||
|
|
||||||
Error connect_to_host(const String &p_uri);
|
Error connect_to_host(const String &p_uri);
|
||||||
|
|
||||||
bool is_peer_connected() override;
|
bool is_peer_connected() override;
|
||||||
int get_max_message_size() const override;
|
int get_max_message_size() const override;
|
||||||
bool has_message() override;
|
bool has_message() override;
|
||||||
|
|
|
@ -184,51 +184,6 @@ Error AudioDriverWeb::capture_stop() {
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NO_THREADS
|
|
||||||
/// ScriptProcessorNode implementation
|
|
||||||
AudioDriverScriptProcessor *AudioDriverScriptProcessor::singleton = nullptr;
|
|
||||||
|
|
||||||
void AudioDriverScriptProcessor::_process_callback() {
|
|
||||||
AudioDriverScriptProcessor::singleton->_audio_driver_capture();
|
|
||||||
AudioDriverScriptProcessor::singleton->_audio_driver_process();
|
|
||||||
}
|
|
||||||
|
|
||||||
Error AudioDriverScriptProcessor::create(int &p_buffer_samples, int p_channels) {
|
|
||||||
if (!godot_audio_has_script_processor()) {
|
|
||||||
return ERR_UNAVAILABLE;
|
|
||||||
}
|
|
||||||
return (Error)godot_audio_script_create(&p_buffer_samples, p_channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioDriverScriptProcessor::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) {
|
|
||||||
godot_audio_script_start(p_in_buf, p_in_buf_size, p_out_buf, p_out_buf_size, &_process_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// AudioWorkletNode implementation (no threads)
|
|
||||||
AudioDriverWorklet *AudioDriverWorklet::singleton = nullptr;
|
|
||||||
|
|
||||||
Error AudioDriverWorklet::create(int &p_buffer_size, int p_channels) {
|
|
||||||
if (!godot_audio_has_worklet()) {
|
|
||||||
return ERR_UNAVAILABLE;
|
|
||||||
}
|
|
||||||
return (Error)godot_audio_worklet_create(p_channels);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioDriverWorklet::start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) {
|
|
||||||
_audio_driver_process();
|
|
||||||
godot_audio_worklet_start_no_threads(p_out_buf, p_out_buf_size, &_process_callback, p_in_buf, p_in_buf_size, &_capture_callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioDriverWorklet::_process_callback(int p_pos, int p_samples) {
|
|
||||||
AudioDriverWorklet *driver = AudioDriverWorklet::singleton;
|
|
||||||
driver->_audio_driver_process(p_pos, p_samples);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioDriverWorklet::_capture_callback(int p_pos, int p_samples) {
|
|
||||||
AudioDriverWorklet *driver = AudioDriverWorklet::singleton;
|
|
||||||
driver->_audio_driver_capture(p_pos, p_samples);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/// AudioWorkletNode implementation (threads)
|
/// AudioWorkletNode implementation (threads)
|
||||||
void AudioDriverWorklet::_audio_thread_func(void *p_data) {
|
void AudioDriverWorklet::_audio_thread_func(void *p_data) {
|
||||||
AudioDriverWorklet *driver = static_cast<AudioDriverWorklet *>(p_data);
|
AudioDriverWorklet *driver = static_cast<AudioDriverWorklet *>(p_data);
|
||||||
|
@ -290,4 +245,3 @@ void AudioDriverWorklet::finish_driver() {
|
||||||
quit = true; // Ask thread to quit.
|
quit = true; // Ask thread to quit.
|
||||||
thread.wait_to_finish();
|
thread.wait_to_finish();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -89,46 +89,6 @@ public:
|
||||||
AudioDriverWeb() {}
|
AudioDriverWeb() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NO_THREADS
|
|
||||||
class AudioDriverScriptProcessor : public AudioDriverWeb {
|
|
||||||
private:
|
|
||||||
static void _process_callback();
|
|
||||||
|
|
||||||
static AudioDriverScriptProcessor *singleton;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Error create(int &p_buffer_samples, int p_channels) override;
|
|
||||||
void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual const char *get_name() const override { return "ScriptProcessor"; }
|
|
||||||
|
|
||||||
virtual void lock() override {}
|
|
||||||
virtual void unlock() override {}
|
|
||||||
|
|
||||||
AudioDriverScriptProcessor() { singleton = this; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class AudioDriverWorklet : public AudioDriverWeb {
|
|
||||||
private:
|
|
||||||
static void _process_callback(int p_pos, int p_samples);
|
|
||||||
static void _capture_callback(int p_pos, int p_samples);
|
|
||||||
|
|
||||||
static AudioDriverWorklet *singleton;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual Error create(int &p_buffer_size, int p_output_channels) override;
|
|
||||||
virtual void start(float *p_out_buf, int p_out_buf_size, float *p_in_buf, int p_in_buf_size) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual const char *get_name() const override { return "AudioWorklet"; }
|
|
||||||
|
|
||||||
virtual void lock() override {}
|
|
||||||
virtual void unlock() override {}
|
|
||||||
|
|
||||||
AudioDriverWorklet() { singleton = this; }
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
class AudioDriverWorklet : public AudioDriverWeb {
|
class AudioDriverWorklet : public AudioDriverWeb {
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
|
@ -156,6 +116,5 @@ public:
|
||||||
void lock() override;
|
void lock() override;
|
||||||
void unlock() override;
|
void unlock() override;
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // AUDIO_DRIVER_WEB_H
|
#endif // AUDIO_DRIVER_WEB_H
|
||||||
|
|
|
@ -239,9 +239,6 @@ OS_Web::OS_Web() {
|
||||||
godot_js_pwa_cb(&OS_Web::update_pwa_state_callback);
|
godot_js_pwa_cb(&OS_Web::update_pwa_state_callback);
|
||||||
|
|
||||||
if (AudioDriverWeb::is_available()) {
|
if (AudioDriverWeb::is_available()) {
|
||||||
#ifdef NO_THREADS
|
|
||||||
audio_drivers.push_back(memnew(AudioDriverScriptProcessor));
|
|
||||||
#endif
|
|
||||||
audio_drivers.push_back(memnew(AudioDriverWorklet));
|
audio_drivers.push_back(memnew(AudioDriverWorklet));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < audio_drivers.size(); i++) {
|
for (int i = 0; i < audio_drivers.size(); i++) {
|
||||||
|
|
|
@ -261,12 +261,7 @@ void NavigationRegion3D::bake_navigation_mesh(bool p_on_thread) {
|
||||||
BakeThreadsArgs *args = memnew(BakeThreadsArgs);
|
BakeThreadsArgs *args = memnew(BakeThreadsArgs);
|
||||||
args->nav_region = this;
|
args->nav_region = this;
|
||||||
|
|
||||||
if (p_on_thread && !OS::get_singleton()->can_use_threads()) {
|
if (p_on_thread) {
|
||||||
WARN_PRINT("NavigationMesh bake 'on_thread' will be disabled as the current OS does not support multiple threads."
|
|
||||||
"\nAs a fallback the navigation mesh will bake on the main thread which can cause framerate issues.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_on_thread && OS::get_singleton()->can_use_threads()) {
|
|
||||||
bake_thread.start(_bake_navigation_mesh, args);
|
bake_thread.start(_bake_navigation_mesh, args);
|
||||||
} else {
|
} else {
|
||||||
_bake_navigation_mesh(args);
|
_bake_navigation_mesh(args);
|
||||||
|
|
|
@ -116,19 +116,11 @@ void AudioEffectRecordInstance::init() {
|
||||||
recording_data.clear(); //Clear data completely and reset length
|
recording_data.clear(); //Clear data completely and reset length
|
||||||
is_recording = true;
|
is_recording = true;
|
||||||
|
|
||||||
#ifdef NO_THREADS
|
|
||||||
AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
|
|
||||||
#else
|
|
||||||
io_thread.start(_thread_callback, this);
|
io_thread.start(_thread_callback, this);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEffectRecordInstance::finish() {
|
void AudioEffectRecordInstance::finish() {
|
||||||
#ifdef NO_THREADS
|
|
||||||
AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
|
|
||||||
#else
|
|
||||||
io_thread.wait_to_finish();
|
io_thread.wait_to_finish();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioEffectRecordInstance::~AudioEffectRecordInstance() {
|
AudioEffectRecordInstance::~AudioEffectRecordInstance() {
|
||||||
|
|
|
@ -38,8 +38,6 @@
|
||||||
#include "core/templates/command_queue_mt.h"
|
#include "core/templates/command_queue_mt.h"
|
||||||
#include "tests/test_macros.h"
|
#include "tests/test_macros.h"
|
||||||
|
|
||||||
#if !defined(NO_THREADS)
|
|
||||||
|
|
||||||
namespace TestCommandQueue {
|
namespace TestCommandQueue {
|
||||||
|
|
||||||
class ThreadWork {
|
class ThreadWork {
|
||||||
|
@ -426,6 +424,4 @@ TEST_CASE("[Stress][CommandQueue] Stress test command queue") {
|
||||||
}
|
}
|
||||||
} // namespace TestCommandQueue
|
} // namespace TestCommandQueue
|
||||||
|
|
||||||
#endif // !defined(NO_THREADS)
|
|
||||||
|
|
||||||
#endif // TEST_COMMAND_QUEUE_H
|
#endif // TEST_COMMAND_QUEUE_H
|
||||||
|
|
Loading…
Reference in a new issue