Allow Windows platform also add idler with return 74/298974/3
authorEunki, Hong <eunkiki.hong@samsung.com>
Mon, 18 Sep 2023 02:58:43 +0000 (11:58 +0900)
committerEunki Hong <eunkiki.hong@samsung.com>
Mon, 18 Sep 2023 10:23:41 +0000 (19:23 +0900)
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 <eunkiki.hong@samsung.com>
dali/internal/system/windows/callback-manager-win.cpp
dali/internal/system/windows/callback-manager-win.h

index f57945a..6614ff3 100644 (file)
@@ -36,9 +36,40 @@ namespace Internal
 {\r
 namespace Adaptor\r
 {\r
+/**\r
+ * Structure contains the callback function and control options\r
+ */\r
+struct WindowsCallbackData\r
+{\r
+  /**\r
+   * Constructor\r
+   */\r
+  WindowsCallbackData(CallbackBase* callback, bool hasReturnValue)\r
+  : mCallback(callback),\r
+    mHasReturnValue(hasReturnValue)\r
+  {\r
+  }\r
+  /**\r
+   * Destructor\r
+   */\r
+  ~WindowsCallbackData()\r
+  {\r
+    delete mCallback;\r
+  }\r
+\r
+  CallbackBase* mCallback;       ///< call back\r
+  bool          mHasReturnValue; ///< true if the callback function has a return value.\r
+};\r
+\r
 WinCallbackManager::WinCallbackManager()\r
 : mRunning(false)\r
 {\r
+  mSelfCallback = MakeCallback(this, &WinCallbackManager::ProcessIdleFromFramework);\r
+}\r
+\r
+WinCallbackManager::~WinCallbackManager()\r
+{\r
+  delete mSelfCallback;\r
 }\r
 \r
 void WinCallbackManager::Start()\r
@@ -52,6 +83,8 @@ void WinCallbackManager::Stop()
   // make sure we're not called twice\r
   DALI_ASSERT_DEBUG(mRunning == true);\r
 \r
+  ClearIdleCallbacks();\r
+\r
   mRunning = false;\r
 }\r
 \r
@@ -62,35 +95,97 @@ bool WinCallbackManager::AddIdleCallback(CallbackBase* callback, bool hasReturnV
     return false;\r
   }\r
 \r
-  mCallbacks.insert(callback);\r
+  WindowsCallbackData* callbackData = new WindowsCallbackData(callback, hasReturnValue);\r
 \r
-  WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast<uint64_t>(callback), 0);\r
+  mCallbackContainer.push_back(callbackData);\r
+\r
+  if(!mSelfCallbackRegistered)\r
+  {\r
+    // Post only one times.\r
+    mSelfCallbackRegistered = true;\r
+    WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast<uint64_t>(mSelfCallback), 0);\r
+  }\r
 \r
   return true;\r
 }\r
 \r
 void WinCallbackManager::RemoveIdleCallback(CallbackBase* callback)\r
 {\r
-  //Wait for deal\r
+  for(auto iter = mCallbackContainer.begin(), endIter = mCallbackContainer.end(); iter != endIter; ++iter)\r
+  {\r
+    auto* callbackData = *iter;\r
+\r
+    if(callbackData->mCallback == callback)\r
+    {\r
+      // delete our data\r
+      delete callbackData;\r
+\r
+      // Set stored value as nullptr. It will be removed from container after ProcessIdle()\r
+      (*iter) = nullptr;\r
+\r
+      return;\r
+    }\r
+  }\r
 }\r
 \r
 bool WinCallbackManager::ProcessIdle()\r
 {\r
-  const bool idleProcessed = !mCallbacks.empty();\r
+  mSelfCallbackRegistered = false;\r
+\r
+  const bool idleProcessed = !mCallbackContainer.empty();\r
+\r
+  for(auto iter = mCallbackContainer.begin(); iter != mCallbackContainer.end();)\r
+  {\r
+    auto* callbackData = *iter;\r
+    bool  removed      = true;\r
+    if(callbackData)\r
+    {\r
+      if(callbackData->mHasReturnValue)\r
+      {\r
+        const bool retValue = Dali::CallbackBase::ExecuteReturn<bool>(*(callbackData->mCallback));\r
+\r
+        // Do not remove callback if return value is true.\r
+        removed = !retValue;\r
+      }\r
+      else\r
+      {\r
+        Dali::CallbackBase::Execute(*(callbackData->mCallback));\r
+      }\r
+    }\r
+\r
+    if(removed)\r
+    {\r
+      delete (*iter);\r
+      iter = mCallbackContainer.erase(iter);\r
+    }\r
+    else\r
+    {\r
+      ++iter;\r
+    }\r
+  }\r
 \r
-  // @todo : Need to consider callback with return & don't erase callback when it return true.\r
-  for(CallbackBase* cb : mCallbacks)\r
+  // Re-register WIN_CALLBACK_EVENT when some idle callback remained.\r
+  if(!mCallbackContainer.empty())\r
   {\r
-    Dali::CallbackBase::Execute(*cb);\r
+    if(!mSelfCallbackRegistered)\r
+    {\r
+      // Post only one times.\r
+      mSelfCallbackRegistered = true;\r
+      WindowsPlatform::PostWinThreadMessage(WIN_CALLBACK_EVENT, reinterpret_cast<uint64_t>(mSelfCallback), 0);\r
+    }\r
   }\r
-  mCallbacks.clear();\r
 \r
   return idleProcessed;\r
 }\r
 \r
 void WinCallbackManager::ClearIdleCallbacks()\r
 {\r
-  mCallbacks.clear();\r
+  for(auto iter = mCallbackContainer.begin(), endIter = mCallbackContainer.end(); iter != endIter; ++iter)\r
+  {\r
+    auto* callbackData = *iter;\r
+    delete callbackData;\r
+  }\r
+  mCallbackContainer.clear();\r
 }\r
 \r
 bool WinCallbackManager::AddIdleEntererCallback(CallbackBase* callback)\r
@@ -100,6 +195,12 @@ bool WinCallbackManager::AddIdleEntererCallback(CallbackBase* callback)
 \r
 void WinCallbackManager::RemoveIdleEntererCallback(CallbackBase* callback)\r
 {\r
+  RemoveIdleCallback(callback);\r
+}\r
+\r
+void WinCallbackManager::ProcessIdleFromFramework()\r
+{\r
+  ProcessIdle();\r
 }\r
 \r
 } // namespace Adaptor\r
index b648425..f92d551 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 // EXTERNAL INCLUDES
-#include <set>
+#include <dali/public-api/common/list-wrapper.h>
 
 // INTERNAL INCLUDES
 #include <dali/internal/system/common/callback-manager.h>
@@ -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<CallbackBase*> 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<WindowsCallbackData*> CallbackList;
+
+  CallbackList mCallbackContainer;
+  bool         mRunning; ///< flag is set to true if when running
 };
 
 } // namespace Adaptor