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();
}
}
-/// 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);
}
}
// 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();
}
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()
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);
}
*/
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.
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;