Merge pull request #473 from aws-lumberyard-dev/mbalfour/cherrypick-lyn-3411

Cherrypick from 1.0 - [LYN-3411] Editor freezes when saving/reloading slice due to deadlock
This commit is contained in:
Mike Balfour
2021-04-30 13:19:22 -05:00
committed by GitHub
@@ -1454,32 +1454,48 @@ namespace AZ
//=========================================================================
void AssetManager::ReloadAssetFromData(const Asset<AssetData>& asset)
{
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
AZ_Assert(m_assets.find(asset.GetId()) != m_assets.end(), "Unable to reload asset %s because its not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
AZ_Assert(m_assets.find(asset.GetId()) == m_assets.end() || asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
"New and old data types are mismatched!");
bool shouldAssignAssetData = false;
auto found = m_assets.find(asset.GetId());
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
{
return; // this will just lead to crashes down the line and the above asserts cover this.
}
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
AZ_Assert(
m_assets.find(asset.GetId()) != m_assets.end(),
"Unable to reload asset %s because it's not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
AZ_Assert(
m_assets.find(asset.GetId()) == m_assets.end() ||
asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
"New and old data types are mismatched!");
AssetData* newData = asset.Get();
if (found->second != newData)
{
// Notify users that we are about to change asset
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
// Resolve the asset handler and account for the new asset instance.
auto found = m_assets.find(asset.GetId());
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
{
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
AZ_Assert(handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
return; // this will just lead to crashes down the line and the above asserts cover this.
}
AssetData* newData = asset.Get();
if (found->second != newData)
{
// Notify users that we are about to change asset
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
// Resolve the asset handler and account for the new asset instance.
{
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
AZ_Assert(
handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
}
shouldAssignAssetData = true;
}
}
// We specifically perform this outside of the m_assetMutex lock so that the lock isn't held at the point that
// OnAssetReload is triggered inside of AssignAssetData. Otherwise, we open up a high potential for deadlocks.
if (shouldAssignAssetData)
{
AssignAssetData(asset);
}
}