From e0e4d621c44c190d7c3c14baf9e207f0993b3346 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Mon, 18 Sep 2023 11:58:43 +0900 Subject: [PATCH] Allow Windows platform also add idler with return Since current callback-manager-win.cpp only allow to excute non-return value callbackes, we cannot repeat Idle APIs for Windows platforms logically. Now, let we make it possible. Change-Id: I2f6821813817e993cf73c128c091a2e423bd1a56 Signed-off-by: Eunki, Hong --- .../system/windows/callback-manager-win.cpp | 119 +++++++++++++++++++-- .../internal/system/windows/callback-manager-win.h | 25 +++-- 2 files changed, 128 insertions(+), 16 deletions(-) diff --git a/dali/internal/system/windows/callback-manager-win.cpp b/dali/internal/system/windows/callback-manager-win.cpp index f57945a..6614ff3 100644 --- a/dali/internal/system/windows/callback-manager-win.cpp +++ b/dali/internal/system/windows/callback-manager-win.cpp @@ -36,9 +36,40 @@ namespace Internal { namespace Adaptor { +/** + * Structure contains the callback function and control options + */ +struct WindowsCallbackData +{ + /** + * Constructor + */ + WindowsCallbackData(CallbackBase* callback, bool hasReturnValue) + : mCallback(callback), + mHasReturnValue(hasReturnValue) + { + } + /** + * Destructor + */ + ~WindowsCallbackData() + { + delete mCallback; + } + + CallbackBase* mCallback; ///< call back + bool mHasReturnValue; ///< true if the callback function has a return value. +}; + WinCallbackManager::WinCallbackManager() : mRunning(false) { + mSelfCallback = MakeCallback(this, &WinCallbackManager::ProcessIdleFromFramework); +} + +WinCallbackManager::~WinCallbackManager() +{ + delete mSelfCallback; } void WinCallbackManager::Start() @@ -52,6 +83,8 @@ void WinCallbackManager::Stop() // make sure we're not called twice DALI_ASSERT_DEBUG(mRunning == true); + ClearIdleCallbacks(); + mRunning = false; } @@ -62,35 +95,97 @@ bool WinCallbackManager::AddIdleCallback(CallbackBase* callback, bool hasReturnV return false; } - mCallbacks.insert(callback); + WindowsCallbackData* callbackData = new WindowsCallbackData(callback, hasReturnValue); - WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast(callback), 0); + mCallbackContainer.push_back(callbackData); + + if(!mSelfCallbackRegistered) + { + // Post only one times. + mSelfCallbackRegistered = true; + WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast(mSelfCallback), 0); + } return true; } void WinCallbackManager::RemoveIdleCallback(CallbackBase* callback) { - //Wait for deal + for(auto iter = mCallbackContainer.begin(), endIter = mCallbackContainer.end(); iter != endIter; ++iter) + { + auto* callbackData = *iter; + + if(callbackData->mCallback == callback) + { + // delete our data + delete callbackData; + + // Set stored value as nullptr. It will be removed from container after ProcessIdle() + (*iter) = nullptr; + + return; + } + } } bool WinCallbackManager::ProcessIdle() { - const bool idleProcessed = !mCallbacks.empty(); + mSelfCallbackRegistered = false; + + const bool idleProcessed = !mCallbackContainer.empty(); + + for(auto iter = mCallbackContainer.begin(); iter != mCallbackContainer.end();) + { + auto* callbackData = *iter; + bool removed = true; + if(callbackData) + { + if(callbackData->mHasReturnValue) + { + const bool retValue = Dali::CallbackBase::ExecuteReturn(*(callbackData->mCallback)); + + // Do not remove callback if return value is true. + removed = !retValue; + } + else + { + Dali::CallbackBase::Execute(*(callbackData->mCallback)); + } + } + + if(removed) + { + delete (*iter); + iter = mCallbackContainer.erase(iter); + } + else + { + ++iter; + } + } - // @todo : Need to consider callback with return & don't erase callback when it return true. - for(CallbackBase* cb : mCallbacks) + // Re-register WIN_CALLBACK_EVENT when some idle callback remained. + if(!mCallbackContainer.empty()) { - Dali::CallbackBase::Execute(*cb); + if(!mSelfCallbackRegistered) + { + // Post only one times. + mSelfCallbackRegistered = true; + WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast(mSelfCallback), 0); + } } - mCallbacks.clear(); return idleProcessed; } void WinCallbackManager::ClearIdleCallbacks() { - mCallbacks.clear(); + for(auto iter = mCallbackContainer.begin(), endIter = mCallbackContainer.end(); iter != endIter; ++iter) + { + auto* callbackData = *iter; + delete callbackData; + } + mCallbackContainer.clear(); } bool WinCallbackManager::AddIdleEntererCallback(CallbackBase* callback) @@ -100,6 +195,12 @@ bool WinCallbackManager::AddIdleEntererCallback(CallbackBase* callback) void WinCallbackManager::RemoveIdleEntererCallback(CallbackBase* callback) { + RemoveIdleCallback(callback); +} + +void WinCallbackManager::ProcessIdleFromFramework() +{ + ProcessIdle(); } } // namespace Adaptor diff --git a/dali/internal/system/windows/callback-manager-win.h b/dali/internal/system/windows/callback-manager-win.h index b648425..f92d551 100644 --- a/dali/internal/system/windows/callback-manager-win.h +++ b/dali/internal/system/windows/callback-manager-win.h @@ -19,7 +19,7 @@ */ // EXTERNAL INCLUDES -#include +#include // INTERNAL INCLUDES #include @@ -30,8 +30,10 @@ namespace Internal { namespace Adaptor { +struct WindowsCallbackData; + /** - * @brief LibUV callback manager used to install call backs in the applications main loop. + * @brief Windows callback manager used to install call backs in the applications main loop. * The manager keeps track of all callbacks, so that if Stop() is called it can remove them. */ class WinCallbackManager : public CallbackManager @@ -45,9 +47,7 @@ public: /** * @brief destructor */ - ~WinCallbackManager() - { - } + ~WinCallbackManager(); /** * @copydoc CallbackManager::AddIdleCallback() @@ -110,9 +110,20 @@ private: WinCallbackManager(const WinCallbackManager&) = delete; WinCallbackManager& operator=(WinCallbackManager&) = delete; + /** + * @brief Callback function comes from framework. + * It will be self callback. + */ + void ProcessIdleFromFramework(); + private: - std::set mCallbacks; - bool mRunning; ///< flag is set to true if when running + CallbackBase* mSelfCallback{nullptr}; + bool mSelfCallbackRegistered{false}; ///< flag is set to true if we send processIdle callback register. + + typedef std::list CallbackList; + + CallbackList mCallbackContainer; + bool mRunning; ///< flag is set to true if when running }; } // namespace Adaptor -- 2.7.4