From 9998683d2be5f3474f1d4a29fd6210cb2bd79d63 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Thu, 12 Feb 2026 04:09:52 +0800 Subject: [PATCH 1/6] Replace Ecore Queue with Message Loop --- .../platform/tizen/tizen_vsync_waiter.cc | 130 +++++++----------- .../shell/platform/tizen/tizen_vsync_waiter.h | 36 ++++- 2 files changed, 79 insertions(+), 87 deletions(-) diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc index ce28d8b9..226bf45a 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc @@ -3,107 +3,78 @@ // found in the LICENSE file. #include "tizen_vsync_waiter.h" - -#include - #include "flutter/shell/platform/tizen/flutter_tizen_engine.h" #include "flutter/shell/platform/tizen/logger.h" namespace flutter { -namespace { - -constexpr int kMessageQuit = -1; -constexpr int kMessageRequestVblank = 0; - -struct Message { - Eina_Thread_Queue_Msg head; - int event; - intptr_t baton; -}; - -} // namespace - -TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine) { - tdm_client_ = std::make_shared(engine); - - vblank_thread_ = ecore_thread_feedback_run(RunVblankLoop, nullptr, nullptr, - nullptr, this, EINA_TRUE); +MessageLoop::MessageLoop() : quit_(false) { + Init(); } - -TizenVsyncWaiter::~TizenVsyncWaiter() { - tdm_client_->OnEngineStop(); - - SendMessage(kMessageQuit, 0); - - if (vblank_thread_) { - ecore_thread_cancel(vblank_thread_); - vblank_thread_ = nullptr; - } +MessageLoop::~MessageLoop() { + Quit(); } -void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) { - SendMessage(kMessageRequestVblank, baton); +void MessageLoop::Init() { + quit_ = false; + loop_thread_ = std::thread(&MessageLoop::Run, this); + FT_LOG(Info) << "[MessageLoop] Thread started."; } -void TizenVsyncWaiter::SendMessage(int event, intptr_t baton) { - if (!vblank_thread_ || ecore_thread_check(vblank_thread_)) { - FT_LOG(Error) << "Invalid vblank thread."; - return; +void MessageLoop::Quit() { + { + std::lock_guard lock(mutex_); + if (quit_) + return; + quit_ = true; } + cond_.notify_all(); - if (!vblank_thread_queue_) { - FT_LOG(Error) << "Invalid vblank thread queue."; - return; + if (loop_thread_.joinable()) { + loop_thread_.join(); + FT_LOG(Info) << "[MessageLoop] Thread joined and quit."; } - - void* ref; - Message* message = static_cast( - eina_thread_queue_send(vblank_thread_queue_, sizeof(Message), &ref)); - message->event = event; - message->baton = baton; - eina_thread_queue_send_done(vblank_thread_queue_, ref); } -void TizenVsyncWaiter::RunVblankLoop(void* data, Ecore_Thread* thread) { - auto* self = static_cast(data); - - std::weak_ptr tdm_client = self->tdm_client_; - if (!tdm_client.lock()->IsValid()) { - FT_LOG(Error) << "Invalid tdm_client."; - ecore_thread_cancel(thread); - return; +void MessageLoop::PostTask(Task task) { + { + std::lock_guard lock(mutex_); + tasks_.push(std::move(task)); } + cond_.notify_one(); +} - Eina_Thread_Queue* vblank_thread_queue = eina_thread_queue_new(); - if (!vblank_thread_queue) { - FT_LOG(Error) << "Invalid vblank thread queue."; - ecore_thread_cancel(thread); - return; - } - self->vblank_thread_queue_ = vblank_thread_queue; - - while (!ecore_thread_check(thread)) { - void* ref; - Message* message = static_cast( - eina_thread_queue_wait(vblank_thread_queue, &ref)); - if (message->event == kMessageQuit) { - eina_thread_queue_wait_done(vblank_thread_queue, ref); - break; +void MessageLoop::Run() { + while (true) { + Task task; + { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this] { return !tasks_.empty() || quit_; }); + if (quit_) { + break; + } + + task = std::move(tasks_.front()); + tasks_.pop(); } - intptr_t baton = message->baton; - eina_thread_queue_wait_done(vblank_thread_queue, ref); - if (tdm_client.expired()) { - break; + if (task) { + task(); } - tdm_client.lock()->AwaitVblank(baton); } +} - if (vblank_thread_queue) { - eina_thread_queue_free(vblank_thread_queue); - self->vblank_thread_queue_ = nullptr; - } +TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine) { + tdm_client_ = std::make_shared(engine); + message_loop_ = std::make_unique(); +} + +TizenVsyncWaiter::~TizenVsyncWaiter() { + tdm_client_->OnEngineStop(); +} + +void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) { + message_loop_->PostTask([this, baton]() { tdm_client_->AwaitVblank(baton); }); } TdmClient::TdmClient(FlutterTizenEngine* engine) { @@ -126,7 +97,6 @@ TdmClient::TdmClient(FlutterTizenEngine* engine) { return; } tdm_client_vblank_set_enable_fake(vblank_, 1); - engine_ = engine; } diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.h b/flutter/shell/platform/tizen/tizen_vsync_waiter.h index 627fc6f0..2df5afba 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.h +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.h @@ -5,11 +5,15 @@ #ifndef EMBEDDER_TIZEN_VSYNC_WAITER_H_ #define EMBEDDER_TIZEN_VSYNC_WAITER_H_ -#include #include +#include +#include +#include #include #include +#include +#include #include "flutter/shell/platform/embedder/embedder.h" @@ -44,21 +48,39 @@ class TdmClient { intptr_t baton_ = 0; }; +class MessageLoop { + public: + using Task = std::function; + + MessageLoop(); + + ~MessageLoop(); + + void PostTask(Task task); + void Init(); + void Quit(); + + private: + void Run(); + + std::queue tasks_; + std::mutex mutex_; + std::condition_variable cond_; + std::atomic quit_; + std::thread loop_thread_; +}; + class TizenVsyncWaiter { public: + using Task = std::function; TizenVsyncWaiter(FlutterTizenEngine* engine); virtual ~TizenVsyncWaiter(); void AsyncWaitForVsync(intptr_t baton); private: - void SendMessage(int event, intptr_t baton); - - static void RunVblankLoop(void* data, Ecore_Thread* thread); - std::shared_ptr tdm_client_; - Ecore_Thread* vblank_thread_ = nullptr; - Eina_Thread_Queue* vblank_thread_queue_ = nullptr; + std::unique_ptr message_loop_; }; } // namespace flutter From 772ccd9f2fd1d4848d98034b266e1cee5eb44934 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Thu, 12 Feb 2026 04:31:54 +0800 Subject: [PATCH 2/6] Add weak_ptr for tdm cline when post task --- flutter/shell/platform/tizen/tizen_vsync_waiter.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc index 226bf45a..342edbd9 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc @@ -74,7 +74,14 @@ TizenVsyncWaiter::~TizenVsyncWaiter() { } void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) { - message_loop_->PostTask([this, baton]() { tdm_client_->AwaitVblank(baton); }); + std::weak_ptr tdm_client = tdm_client_; + message_loop_->PostTask([tdm_client_weak = std::move(tdm_client), baton]() { + if (auto tdm_client = tdm_client_weak.lock()) { + tdm_client->AwaitVblank(baton); + } else { + FT_LOG(Error) << "tdm client is null, task cancelled"; + } + }); } TdmClient::TdmClient(FlutterTizenEngine* engine) { From c800d505c05b36b58c5716b4376772b0d917ed5d Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Thu, 12 Feb 2026 20:51:29 +0800 Subject: [PATCH 3/6] Remove init method --- flutter/shell/platform/tizen/tizen_vsync_waiter.cc | 9 ++------- flutter/shell/platform/tizen/tizen_vsync_waiter.h | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc index 342edbd9..eb76cac3 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc @@ -9,18 +9,13 @@ namespace flutter { MessageLoop::MessageLoop() : quit_(false) { - Init(); + loop_thread_ = std::thread(&MessageLoop::Run, this); + FT_LOG(Info) << "[MessageLoop] Thread started."; } MessageLoop::~MessageLoop() { Quit(); } -void MessageLoop::Init() { - quit_ = false; - loop_thread_ = std::thread(&MessageLoop::Run, this); - FT_LOG(Info) << "[MessageLoop] Thread started."; -} - void MessageLoop::Quit() { { std::lock_guard lock(mutex_); diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.h b/flutter/shell/platform/tizen/tizen_vsync_waiter.h index 2df5afba..57b8d09b 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.h +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.h @@ -57,7 +57,6 @@ class MessageLoop { ~MessageLoop(); void PostTask(Task task); - void Init(); void Quit(); private: From 3ac00a006c3427e01488beca46a088984b865c2a Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Thu, 12 Feb 2026 22:02:44 +0800 Subject: [PATCH 4/6] Make MessageLoop class private --- .../platform/tizen/tizen_vsync_waiter.cc | 58 +------------ .../shell/platform/tizen/tizen_vsync_waiter.h | 83 ++++++++++++++----- 2 files changed, 63 insertions(+), 78 deletions(-) diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc index eb76cac3..578e4f35 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc @@ -8,61 +8,9 @@ namespace flutter { -MessageLoop::MessageLoop() : quit_(false) { - loop_thread_ = std::thread(&MessageLoop::Run, this); - FT_LOG(Info) << "[MessageLoop] Thread started."; -} -MessageLoop::~MessageLoop() { - Quit(); -} - -void MessageLoop::Quit() { - { - std::lock_guard lock(mutex_); - if (quit_) - return; - quit_ = true; - } - cond_.notify_all(); - - if (loop_thread_.joinable()) { - loop_thread_.join(); - FT_LOG(Info) << "[MessageLoop] Thread joined and quit."; - } -} - -void MessageLoop::PostTask(Task task) { - { - std::lock_guard lock(mutex_); - tasks_.push(std::move(task)); - } - cond_.notify_one(); -} - -void MessageLoop::Run() { - while (true) { - Task task; - { - std::unique_lock lock(mutex_); - cond_.wait(lock, [this] { return !tasks_.empty() || quit_; }); - if (quit_) { - break; - } - - task = std::move(tasks_.front()); - tasks_.pop(); - } - - if (task) { - task(); - } - } -} - -TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine) { - tdm_client_ = std::make_shared(engine); - message_loop_ = std::make_unique(); -} +TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine) + : tdm_client_(std::make_shared(engine)), + message_loop_(std::make_unique()) {} TizenVsyncWaiter::~TizenVsyncWaiter() { tdm_client_->OnEngineStop(); diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.h b/flutter/shell/platform/tizen/tizen_vsync_waiter.h index 57b8d09b..69b39f68 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.h +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.h @@ -48,36 +48,73 @@ class TdmClient { intptr_t baton_ = 0; }; -class MessageLoop { - public: - using Task = std::function; - - MessageLoop(); - - ~MessageLoop(); - - void PostTask(Task task); - void Quit(); - - private: - void Run(); - - std::queue tasks_; - std::mutex mutex_; - std::condition_variable cond_; - std::atomic quit_; - std::thread loop_thread_; -}; - class TizenVsyncWaiter { public: - using Task = std::function; TizenVsyncWaiter(FlutterTizenEngine* engine); virtual ~TizenVsyncWaiter(); - void AsyncWaitForVsync(intptr_t baton); private: + class MessageLoop { + public: + using Task = std::function; + + MessageLoop() : quit_(false) { + loop_thread_ = std::thread(&MessageLoop::Run, this); + } + + ~MessageLoop() { Quit(); } + + void PostTask(Task task) { + { + std::lock_guard lock(mutex_); + tasks_.push(std::move(task)); + } + cond_.notify_one(); + } + + void Quit() { + { + std::lock_guard lock(mutex_); + if (quit_) + return; + quit_ = true; + } + cond_.notify_all(); + + if (loop_thread_.joinable()) { + loop_thread_.join(); + } + } + + private: + void Run() { + while (true) { + Task task; + { + std::unique_lock lock(mutex_); + cond_.wait(lock, [this] { return !tasks_.empty() || quit_; }); + if (quit_) { + break; + } + + task = std::move(tasks_.front()); + tasks_.pop(); + } + + if (task) { + task(); + } + } + } + + std::queue tasks_; + std::mutex mutex_; + std::condition_variable cond_; + std::atomic quit_; + std::thread loop_thread_; + }; + std::shared_ptr tdm_client_; std::unique_ptr message_loop_; }; From 21bbe5c204461d61875d33612fe8911d41d3fe48 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Thu, 12 Feb 2026 22:30:16 +0800 Subject: [PATCH 5/6] Add IsValid check for calling VBlank --- flutter/shell/platform/tizen/tizen_vsync_waiter.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc index 578e4f35..9c9513d3 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc @@ -20,7 +20,11 @@ void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) { std::weak_ptr tdm_client = tdm_client_; message_loop_->PostTask([tdm_client_weak = std::move(tdm_client), baton]() { if (auto tdm_client = tdm_client_weak.lock()) { - tdm_client->AwaitVblank(baton); + if (tdm_client->IsValid()) { + tdm_client->AwaitVblank(baton); + } else { + FT_LOG(Error) << "tdm client is invalid, task cancelled"; + } } else { FT_LOG(Error) << "tdm client is null, task cancelled"; } From fd73b8375c218101ff1ab938c4bbbec60a24f9d7 Mon Sep 17 00:00:00 2001 From: Xiaowei Guan Date: Fri, 13 Feb 2026 04:16:45 +0800 Subject: [PATCH 6/6] Add quit check when post a task --- flutter/shell/platform/tizen/tizen_vsync_waiter.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.h b/flutter/shell/platform/tizen/tizen_vsync_waiter.h index 69b39f68..0b6b4590 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.h +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.h @@ -68,6 +68,9 @@ class TizenVsyncWaiter { void PostTask(Task task) { { std::lock_guard lock(mutex_); + if (quit_) { + return; + } tasks_.push(std::move(task)); } cond_.notify_one(); @@ -76,8 +79,9 @@ class TizenVsyncWaiter { void Quit() { { std::lock_guard lock(mutex_); - if (quit_) + if (quit_) { return; + } quit_ = true; } cond_.notify_all();