diff --git a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc index ce28d8b..9c9513d 100644 --- a/flutter/shell/platform/tizen/tizen_vsync_waiter.cc +++ b/flutter/shell/platform/tizen/tizen_vsync_waiter.cc @@ -3,107 +3,32 @@ // 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); -} +TizenVsyncWaiter::TizenVsyncWaiter(FlutterTizenEngine* engine) + : tdm_client_(std::make_shared(engine)), + message_loop_(std::make_unique()) {} TizenVsyncWaiter::~TizenVsyncWaiter() { tdm_client_->OnEngineStop(); - - SendMessage(kMessageQuit, 0); - - if (vblank_thread_) { - ecore_thread_cancel(vblank_thread_); - vblank_thread_ = nullptr; - } } void TizenVsyncWaiter::AsyncWaitForVsync(intptr_t baton) { - SendMessage(kMessageRequestVblank, baton); -} - -void TizenVsyncWaiter::SendMessage(int event, intptr_t baton) { - if (!vblank_thread_ || ecore_thread_check(vblank_thread_)) { - FT_LOG(Error) << "Invalid vblank thread."; - return; - } - - if (!vblank_thread_queue_) { - FT_LOG(Error) << "Invalid vblank thread queue."; - return; - } - - 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; - } - - 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; - } - intptr_t baton = message->baton; - eina_thread_queue_wait_done(vblank_thread_queue, ref); - - if (tdm_client.expired()) { - break; + 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()) { + 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"; } - tdm_client.lock()->AwaitVblank(baton); - } - - if (vblank_thread_queue) { - eina_thread_queue_free(vblank_thread_queue); - self->vblank_thread_queue_ = nullptr; - } + }); } TdmClient::TdmClient(FlutterTizenEngine* engine) { @@ -126,7 +51,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 627fc6f..0b6b459 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" @@ -48,17 +52,75 @@ class TizenVsyncWaiter { public: 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); + 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_); + if (quit_) { + return; + } + 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_; - Ecore_Thread* vblank_thread_ = nullptr; - Eina_Thread_Queue* vblank_thread_queue_ = nullptr; + std::unique_ptr message_loop_; }; } // namespace flutter