diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2023-01-27 22:53:06 +0200 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2023-01-30 20:47:45 +0200 |
commit | 0cc1f4240aecc93f967bab7b27d9b48fd3126a5b (patch) | |
tree | b327dc0e01a4b1f4cf730891ec1b823dd126295b | |
parent | 551f5191e5dbc1d1a43f99b13d5dbbf7f598dc58 (diff) |
[RichTextLabel] Fix thread unsafe `set_physics_process_internal` usage. Use `WorkerThreadPool` instead of creating new threads.
-rw-r--r-- | modules/text_server_adv/text_server_adv.cpp | 3 | ||||
-rw-r--r-- | scene/gui/rich_text_label.cpp | 32 | ||||
-rw-r--r-- | scene/gui/rich_text_label.h | 6 |
3 files changed, 28 insertions, 13 deletions
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index e53aef965a..9b474bf2ce 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -4068,7 +4068,6 @@ void TextServerAdvanced::_realign(ShapedTextDataAdvanced *p_sd) const { RID TextServerAdvanced::_shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const { _THREAD_SAFE_METHOD_ - const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, RID()); @@ -5513,6 +5512,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star } bool TextServerAdvanced::_shaped_text_shape(const RID &p_shaped) { + _THREAD_SAFE_METHOD_ ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, false); @@ -6569,6 +6569,7 @@ TextServerAdvanced::TextServerAdvanced() { } void TextServerAdvanced::_cleanup() { + _THREAD_SAFE_METHOD_ for (const KeyValue<SystemFontKey, SystemFontCache> &E : system_fonts) { const Vector<SystemFontCacheRec> &sysf_cache = E.value.var; for (const SystemFontCacheRec &F : sysf_cache) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 71ee3c8d0d..3051502dd0 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -1797,7 +1797,9 @@ void RichTextLabel::_notification(int p_what) { } break; case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - queue_redraw(); + if (is_visible_in_tree()) { + queue_redraw(); + } } break; case NOTIFICATION_DRAW: { @@ -2665,19 +2667,26 @@ bool RichTextLabel::_find_layout_subitem(Item *from, Item *to) { return false; } -void RichTextLabel::_thread_function(void *self) { - RichTextLabel *rtl = reinterpret_cast<RichTextLabel *>(self); - rtl->set_physics_process_internal(true); - rtl->_process_line_caches(); - rtl->set_physics_process_internal(false); - rtl->updating.store(false); - rtl->call_deferred(SNAME("queue_redraw")); +void RichTextLabel::_thread_function(void *p_userdata) { + _process_line_caches(); + updating.store(false); + call_deferred(SNAME("thread_end")); +} + +void RichTextLabel::_thread_end() { + set_physics_process_internal(false); + if (is_visible_in_tree()) { + queue_redraw(); + } } void RichTextLabel::_stop_thread() { if (threaded) { stop_thread.store(true); - thread.wait_to_finish(); + if (task != WorkerThreadPool::INVALID_TASK_ID) { + WorkerThreadPool::get_singleton()->wait_for_task_completion(task); + task = WorkerThreadPool::INVALID_TASK_ID; + } } } @@ -2787,7 +2796,8 @@ bool RichTextLabel::_validate_line_caches() { if (threaded) { updating.store(true); loaded.store(true); - thread.start(RichTextLabel::_thread_function, reinterpret_cast<void *>(this)); + task = WorkerThreadPool::get_singleton()->add_template_task(this, &RichTextLabel::_thread_function, nullptr, true, vformat("RichTextLabelShape:%x", (int64_t)get_instance_id())); + set_physics_process_internal(true); loading_started = OS::get_singleton()->get_ticks_msec(); return false; } else { @@ -5457,6 +5467,8 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_menu"), &RichTextLabel::get_menu); ClassDB::bind_method(D_METHOD("is_menu_visible"), &RichTextLabel::is_menu_visible); + ClassDB::bind_method(D_METHOD("_thread_end"), &RichTextLabel::_thread_end); + // Note: set "bbcode_enabled" first, to avoid unnecessary "text" resets. ADD_PROPERTY(PropertyInfo(Variant::BOOL, "bbcode_enabled"), "set_use_bbcode", "is_using_bbcode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT), "set_text", "get_text"); diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 58b82d4672..fcbb91f67e 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -31,6 +31,7 @@ #ifndef RICH_TEXT_LABEL_H #define RICH_TEXT_LABEL_H +#include "core/object/worker_thread_pool.h" #include "rich_text_effect.h" #include "scene/gui/popup_menu.h" #include "scene/gui/scroll_bar.h" @@ -369,7 +370,7 @@ private: Item *current = nullptr; ItemFrame *current_frame = nullptr; - Thread thread; + WorkerThreadPool::TaskID task = WorkerThreadPool::INVALID_TASK_ID; Mutex data_mutex; bool threaded = false; std::atomic<bool> stop_thread; @@ -409,7 +410,8 @@ private: void _invalidate_current_line(ItemFrame *p_frame); - static void _thread_function(void *self); + void _thread_function(void *p_userdata); + void _thread_end(); void _stop_thread(); bool _validate_line_caches(); void _process_line_caches(); |