Fix text load observer destruction signal
authorBowon Ryu <bowon.ryu@samsung.com>
Tue, 16 Jul 2024 04:14:53 +0000 (13:14 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Tue, 16 Jul 2024 04:14:53 +0000 (13:14 +0900)
There are cases where one observer requests and receives multiple tasks.
If there are still tasks remaining, the destruction signal should not be disconnected.

Change-Id: Ie78967b78ace4787ef6e2582f5f9cafdffc250c3
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
dali-toolkit/internal/text/async-text/async-text-manager-impl.cpp
dali-toolkit/internal/text/async-text/text-load-observer.cpp
dali-toolkit/internal/text/async-text/text-load-observer.h

index 6821060..a9201c1 100644 (file)
@@ -150,6 +150,7 @@ uint32_t AsyncTextManager::RequestLoad(AsyncTextParameters& parameters, TextLoad
   if(observer)
   {
     DALI_LOG_RELEASE_INFO("RequestLoad -> connect DestructionSignal to observer : %p, task : %u\n", observer, mTaskId);
+    observer->ConnectDestructionSignal();
     observer->DestructionSignal().Connect(this, &AsyncTextManager::ObserverDestroyed);
   }
 
@@ -183,7 +184,10 @@ void AsyncTextManager::RequestCancel(uint32_t taskId)
     if(it->second.mObserver)
     {
       DALI_LOG_RELEASE_INFO("RequestCancel -> ob : %p, remove wating task : %u\n", it->second.mObserver, taskId);
-      it->second.mObserver->DestructionSignal().Disconnect(this, &AsyncTextManager::ObserverDestroyed);
+      if(it->second.mObserver->DisconnectDestructionSignal())
+      {
+        it->second.mObserver->DestructionSignal().Disconnect(this, &AsyncTextManager::ObserverDestroyed);
+      }
     }
     Dali::AsyncTaskManager::Get().RemoveTask(it->second.mTask);
     mWaitingTasks.erase(it);
@@ -197,7 +201,10 @@ void AsyncTextManager::RequestCancel(uint32_t taskId)
       if(it->second.mObserver)
       {
         DALI_LOG_RELEASE_INFO("RequestCancel -> ob : %p, remove running task : %u\n", it->second.mObserver, taskId);
-        it->second.mObserver->DestructionSignal().Disconnect(this, &AsyncTextManager::ObserverDestroyed);
+        if(it->second.mObserver->DisconnectDestructionSignal())
+        {
+          it->second.mObserver->DestructionSignal().Disconnect(this, &AsyncTextManager::ObserverDestroyed);
+        }
       }
       mRunningTasks.erase(it);
       return;
@@ -226,7 +233,10 @@ void AsyncTextManager::LoadComplete(Toolkit::Internal::TextLoadingTaskPtr task)
       DALI_LOG_RELEASE_INFO("LoadComplete -> ob : %p, remove task : %u\n", it->second.mObserver, taskId);
       // TODO : If it fails for any reason, false should be sent.
       bool success = true;
-      it->second.mObserver->DestructionSignal().Disconnect(this, &AsyncTextManager::ObserverDestroyed);
+      if(it->second.mObserver->DisconnectDestructionSignal())
+      {
+        it->second.mObserver->DestructionSignal().Disconnect(this, &AsyncTextManager::ObserverDestroyed);
+      }
       it->second.mObserver->LoadComplete(success, TextLoadObserver::TextInformation(task->mRenderInfo, task->mParameters));
     }
     else
@@ -285,24 +295,30 @@ void AsyncTextManager::ObserverDestroyed(TextLoadObserver* observer)
 {
   DALI_LOG_RELEASE_INFO("-->AsyncTextManager::ObserverDestroyed observer : %p\n", observer);
 
-  for(auto it = mRunningTasks.begin(); it != mRunningTasks.end(); ++ it)
+  for(auto it = mRunningTasks.begin(); it != mRunningTasks.end();)
   {
     if(it->second.mObserver == observer)
     {
       it->second.mObserver = nullptr;
       it = mRunningTasks.erase(it);
-      break;
+    }
+    else
+    {
+      ++it;
     }
   }
 
-  for(auto it = mWaitingTasks.begin(); it != mWaitingTasks.end(); ++ it)
+  for(auto it = mWaitingTasks.begin(); it != mWaitingTasks.end();)
   {
     if(it->second.mObserver == observer)
     {
       Dali::AsyncTaskManager::Get().RemoveTask(it->second.mTask);
       it->second.mObserver = nullptr;
       it = mWaitingTasks.erase(it);
-      break;
+    }
+    else
+    {
+      ++it;
     }
   }
 }
index f9e6b22..6087f5e 100644 (file)
@@ -31,6 +31,7 @@ TextLoadObserver::TextInformation::TextInformation(Text::AsyncTextRenderInfo ren
 }
 
 TextLoadObserver::TextLoadObserver()
+: mDestructionSignalConnect(0)
 {
 }
 
@@ -47,6 +48,21 @@ TextLoadObserver::DestructionSignalType& TextLoadObserver::DestructionSignal()
   return mDestructionSignal;
 }
 
+void TextLoadObserver::ConnectDestructionSignal()
+{
+  mDestructionSignalConnect++;
+}
+
+bool TextLoadObserver::DisconnectDestructionSignal()
+{
+  mDestructionSignalConnect--;
+  if(mDestructionSignalConnect < 0)
+  {
+    mDestructionSignalConnect = 0;
+  }
+  return !mDestructionSignalConnect;
+}
+
 } // namespace Toolkit
 
 } // namespace Dali
index a957b85..bb7b021 100644 (file)
@@ -77,8 +77,22 @@ public:
    */
   DestructionSignalType& DestructionSignal();
 
+  /**
+   * @brief Each time DestructionSignal is connected, the count increases by 1.
+   */
+  void ConnectDestructionSignal();
+
+  /**
+   * @brief Each time DestructionSignal is disconnected, the count decreases by 1.
+   * @return If the count reaches 0, true is returned.
+   */
+  bool DisconnectDestructionSignal();
+
+public:
+
 private:
-  DestructionSignalType mDestructionSignal; ///< The destruction signal emitted when the observer is destroyed.
+  DestructionSignalType mDestructionSignal;        ///< The destruction signal emitted when the observer is destroyed.
+  int                   mDestructionSignalConnect; ///< The number of times DestructionSignal is connected.
 };
 
 } // namespace Toolkit