[Tizen] (Vector) Make SleepThread more thread safe enough 15/316215/1
authorEunki, Hong <eunkiki.hong@samsung.com>
Wed, 14 Aug 2024 01:49:50 +0000 (10:49 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 16 Aug 2024 04:37:45 +0000 (13:37 +0900)
Make sleep thread destroyed more early time.
It will make that sleepthread cannot call invalid mAwakeCallback.

Also, Make more thread safety when we change the timepoint and sleep

Change-Id: I0ce82503576efff045a45dfdec219f483c08ba03
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.cpp
dali-toolkit/internal/visuals/animated-vector-image/vector-animation-thread.h

index 8a4ce55f58fc13fd99b343fbc80c663f15a39020..e4c8ebd4b45fac9ba5e837015fe8d7c9e8f00164 100644 (file)
@@ -84,6 +84,9 @@ VectorAnimationThread::~VectorAnimationThread()
 
   DALI_LOG_INFO(gVectorAnimationLogFilter, Debug::Verbose, "VectorAnimationThread::~VectorAnimationThread: Join [%p]\n", this);
 
+  // Mark as sleep thread destroyed now.
+  mSleepThread.Finalize();
+
   DALI_LOG_DEBUG_INFO("VectorAnimationThread Join request\n");
 
   Join();
@@ -120,14 +123,16 @@ void VectorAnimationThread::OnTaskCompleted(VectorAnimationTaskPtr task, bool su
   }
 }
 
-/// VectorAnimationThread::SleepThread called
+/// VectorAnimationThread::SleepThread called, Mutex SleepThread::mAwakeCallbackMutex is locked
 void VectorAnimationThread::OnAwakeFromSleep()
 {
   if(DALI_LIKELY(!mDestroyThread))
   {
+    ConditionalWait::ScopedLock lock(mConditionalWait);
+
     mNeedToSleep = false;
     // wake up the animation thread
-    mConditionalWait.Notify();
+    mConditionalWait.Notify(lock);
   }
 }
 
@@ -412,11 +417,13 @@ VectorAnimationThread::SleepThread::~SleepThread()
   // Stop the thread
   {
     ConditionalWait::ScopedLock lock(mConditionalWait);
-    mDestroyThread = true;
-    mAwakeCallback.reset();
+    Finalize();
+
     mConditionalWait.Notify(lock);
   }
 
+  DALI_LOG_DEBUG_INFO("VectorAnimationThread::SleepThread Join request\n");
+
   Join();
 }
 
@@ -424,9 +431,27 @@ VectorAnimationThread::SleepThread::~SleepThread()
 void VectorAnimationThread::SleepThread::SleepUntil(std::chrono::time_point<std::chrono::steady_clock> timeToSleepUntil)
 {
   ConditionalWait::ScopedLock lock(mConditionalWait);
-  mSleepTimePoint = timeToSleepUntil;
-  mNeedToSleep    = true;
-  mConditionalWait.Notify(lock);
+
+  Mutex::ScopedLock sleepLock(mSleepRequestMutex);
+
+  if(DALI_LIKELY(!mDestroyThread))
+  {
+    mSleepTimePoint = timeToSleepUntil;
+    mNeedToSleep    = true;
+    mConditionalWait.Notify(lock);
+  }
+}
+
+void VectorAnimationThread::SleepThread::Finalize()
+{
+  Mutex::ScopedLock awakeLock(mAwakeCallbackMutex);
+  Mutex::ScopedLock sleepLock(mSleepRequestMutex);
+  if(DALI_LIKELY(!mDestroyThread))
+  {
+    DALI_LOG_DEBUG_INFO("Mark VectorAnimationThread::SleepThread destroyed\n");
+    mDestroyThread = true;
+  }
+  mAwakeCallback.reset();
 }
 
 void VectorAnimationThread::SleepThread::Run()
@@ -437,31 +462,39 @@ void VectorAnimationThread::SleepThread::Run()
 
   while(!mDestroyThread)
   {
-    bool                                               needToSleep;
+    bool needToSleep = false;
+
     std::chrono::time_point<std::chrono::steady_clock> sleepTimePoint;
 
     {
       ConditionalWait::ScopedLock lock(mConditionalWait);
+      Mutex::ScopedLock           sleepLock(mSleepRequestMutex);
 
-      needToSleep    = mNeedToSleep;
-      sleepTimePoint = mSleepTimePoint;
+      if(DALI_LIKELY(!mDestroyThread))
+      {
+        needToSleep    = mNeedToSleep;
+        sleepTimePoint = mSleepTimePoint;
 
-      mNeedToSleep = false;
+        mNeedToSleep = false;
+      }
     }
 
     if(needToSleep)
     {
       std::this_thread::sleep_until(sleepTimePoint);
 
-      if(mAwakeCallback)
       {
-        CallbackBase::Execute(*mAwakeCallback);
+        Mutex::ScopedLock awakeLock(mAwakeCallbackMutex);
+        if(DALI_LIKELY(mAwakeCallback))
+        {
+          CallbackBase::Execute(*mAwakeCallback);
+        }
       }
     }
 
     {
       ConditionalWait::ScopedLock lock(mConditionalWait);
-      if(!mDestroyThread && !mNeedToSleep)
+      if(DALI_LIKELY(!mDestroyThread) && !mNeedToSleep)
       {
         mConditionalWait.Wait(lock);
       }
index ac5053b70d6f0b71a1209411e5358af815dd7aff..22d82ce3a23d6400116290060a1771cdf00a42da 100644 (file)
@@ -150,6 +150,11 @@ private:
      */
     void SleepUntil(std::chrono::time_point<std::chrono::steady_clock> timeToSleepUntil);
 
+    /**
+     * @brief Finalizes the sleep thread. This will make ensure that we don't touch VectorAnimationThread.
+     */
+    void Finalize();
+
   protected:
     /**
      * @brief The entry function of the animation thread.
@@ -161,7 +166,10 @@ private:
     SleepThread& operator=(const SleepThread& thread) = delete;
 
   private:
-    ConditionalWait                                    mConditionalWait;
+    ConditionalWait mConditionalWait;
+    Mutex           mAwakeCallbackMutex; ///< Mutex to check validatoin of mAwakeCallback
+    Mutex           mSleepRequestMutex;  ///< Mutex to change sleep time point.
+
     std::unique_ptr<CallbackBase>                      mAwakeCallback;
     std::chrono::time_point<std::chrono::steady_clock> mSleepTimePoint;
     const Dali::LogFactoryInterface&                   mLogFactory;