Currently, if the AnimatedVectorImageVisual is not destroyed
on Application::Terminate, e.g. if it's actor is kept alive,
then the shutdown order is undefined, and may end up
trying to pend on a mutex which has already been destroyed,
in the dali-extension plugin.
(TizenVectorAnimationManager, which creates the mutex, is a
singleton that is created when first needed, but stays alive
until main() completes)
Prevented the destructor from finalizing in the plugin if
core has already been shutdown.
Change-Id: I9fe547eab4dc3f3e5a4655f5c8dcf96bf664d7e3
mPlacementActor(),
mPlayState( DevelImageVisual::PlayState::STOPPED ),
mEventCallback( nullptr ),
mPlacementActor(),
mPlayState( DevelImageVisual::PlayState::STOPPED ),
mEventCallback( nullptr ),
- mRendererAdded( false )
+ mRendererAdded( false ),
+ mCoreShutdown(false)
{
// the rasterized image is with pre-multiplied alpha format
mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
{
// the rasterized image is with pre-multiplied alpha format
mImpl->mFlags |= Impl::IS_PREMULTIPLIED_ALPHA;
mVectorAnimationTask->UploadCompletedSignal().Connect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
mVectorAnimationTask->SetAnimationFinishedCallback( new EventThreadCallback( MakeCallback( this, &AnimatedVectorImageVisual::OnAnimationFinished ) ) );
+
+ auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+ vectorAnimationManager.AddObserver(*this);
}
AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
{
}
AnimatedVectorImageVisual::~AnimatedVectorImageVisual()
{
- mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+ auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+ vectorAnimationManager.RemoveObserver(*this);
+
+ if( mEventCallback )
+ {
+ mFactoryCache.GetVectorAnimationManager().UnregisterEventCallback( mEventCallback );
+ }
+
+ // Finalize animation task and disconnect the signal in the main thread
+ mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
+ mVectorAnimationTask->Finalize();
- // Finalize animation task and disconnect the signal in the main thread
- mVectorAnimationTask->UploadCompletedSignal().Disconnect( this, &AnimatedVectorImageVisual::OnUploadCompleted );
- mVectorAnimationTask->Finalize();
+void AnimatedVectorImageVisual::VectorAnimationManagerDestroyed()
+{
+ // Core is shutting down. Don't talk to the plugin any more.
+ mCoreShutdown = true;
}
void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
}
void AnimatedVectorImageVisual::GetNaturalSize( Vector2& naturalSize )
void AnimatedVectorImageVisual::TriggerVectorRasterization()
{
void AnimatedVectorImageVisual::TriggerVectorRasterization()
{
+ if( !mEventCallback && !mCoreShutdown )
{
mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents );
{
mEventCallback = MakeCallback( this, &AnimatedVectorImageVisual::OnProcessEvents );
- mFactoryCache.GetVectorAnimationManager().RegisterEventCallback( mEventCallback );
+ auto& vectorAnimationManager = mFactoryCache.GetVectorAnimationManager();
+ vectorAnimationManager.RegisterEventCallback( mEventCallback );
Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing
}
}
Stage::GetCurrent().KeepRendering( 0.0f ); // Trigger event processing
}
}
#include <dali-toolkit/internal/visuals/visual-url.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h>
#include <dali-toolkit/internal/visuals/visual-url.h>
#include <dali-toolkit/devel-api/visuals/animated-vector-image-visual-actions-devel.h>
#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-task.h>
+#include <dali-toolkit/internal/visuals/animated-vector-image/vector-animation-manager.h>
-class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker
+class AnimatedVectorImageVisual: public Visual::Base, public ConnectionTracker, public VectorAnimationManager::LifecycleObserver
*/
void DoCreateInstancePropertyMap( Property::Map& map ) const override;
*/
void DoCreateInstancePropertyMap( Property::Map& map ) const override;
+protected: // From VectorAnimationManager::LifecycleObserver:
+ /**
+ * @copydoc VectorAnimationManager::LifecycleObserver::VectorAnimationManagerDestroyed()
+ */
+ void VectorAnimationManagerDestroyed() override;
+
DevelImageVisual::PlayState::Type mPlayState;
CallbackBase* mEventCallback; // Not owned
bool mRendererAdded;
DevelImageVisual::PlayState::Type mPlayState;
CallbackBase* mEventCallback; // Not owned
bool mRendererAdded;
};
} // namespace Internal
};
} // namespace Internal
VectorAnimationManager::VectorAnimationManager()
: mEventCallbacks(),
VectorAnimationManager::VectorAnimationManager()
: mEventCallbacks(),
mVectorAnimationThread( nullptr ),
mProcessorRegistered( false )
{
mVectorAnimationThread( nullptr ),
mProcessorRegistered( false )
{
{
Adaptor::Get().UnregisterProcessor( *this );
}
{
Adaptor::Get().UnregisterProcessor( *this );
}
+
+ for( auto observer : mLifecycleObservers )
+ {
+ observer->VectorAnimationManagerDestroyed();
+ }
+}
+
+void VectorAnimationManager::AddObserver( VectorAnimationManager::LifecycleObserver& observer )
+{
+ DALI_ASSERT_DEBUG( mLifecycleObservers.end() == std::find( mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer));
+ mLifecycleObservers.push_back( &observer );
+}
+
+void VectorAnimationManager::RemoveObserver( VectorAnimationManager::LifecycleObserver& observer)
+{
+ auto iterator=std::find(mLifecycleObservers.begin(), mLifecycleObservers.end(), &observer);
+ if( iterator != mLifecycleObservers.end() )
+ {
+ mLifecycleObservers.erase(iterator);
+ }
}
VectorAnimationThread& VectorAnimationManager::GetVectorAnimationThread()
}
VectorAnimationThread& VectorAnimationManager::GetVectorAnimationThread()
class VectorAnimationManager: public Integration::Processor
{
public:
class VectorAnimationManager: public Integration::Processor
{
public:
+ struct LifecycleObserver
+ {
+ virtual void VectorAnimationManagerDestroyed() = 0;
+ };
/**
* @brief Constructor.
/**
* @brief Constructor.
~VectorAnimationManager() override;
/**
~VectorAnimationManager() override;
/**
+ * Add a lifecycle observer
+ * @param[in] observer The object watching this one
+ */
+ void AddObserver( LifecycleObserver& observer );
+
+ /**
+ * Remove a lifecycle observer
+ * @param[in] observer The object watching this one
+ */
+ void RemoveObserver( LifecycleObserver& observer );
+
+ /**
* Get the vector animation thread.
* @return A raw pointer pointing to the vector animation thread.
*/
* Get the vector animation thread.
* @return A raw pointer pointing to the vector animation thread.
*/
private:
std::vector< CallbackBase* > mEventCallbacks;
private:
std::vector< CallbackBase* > mEventCallbacks;
+ std::vector<LifecycleObserver*> mLifecycleObservers;
std::unique_ptr< VectorAnimationThread > mVectorAnimationThread;
bool mProcessorRegistered;
};
std::unique_ptr< VectorAnimationThread > mVectorAnimationThread;
bool mProcessorRegistered;
};