Fixed crash when resources in use by the Renderer are released

Former-commit-id: 98eedb556f0387f0a5c1cafde2fc74645d1d0457
This commit is contained in:
Lynix
2013-08-26 00:40:45 +02:00
parent f1dc7b98e5
commit 72a57fbf4c
11 changed files with 228 additions and 42 deletions

View File

@@ -6,6 +6,7 @@
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ResourceListener.hpp>
#include <Nazara/Utility/StaticMesh.hpp>
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <typeinfo>
#include <Nazara/Core/Debug.hpp>
@@ -21,7 +22,7 @@ NzResource::~NzResource()
{
m_resourceListenersLocked = true;
for (auto& pair : m_resourceListeners)
pair.first->OnResourceReleased(this, pair.second);
pair.first->OnResourceReleased(this, pair.second.first);
#if NAZARA_CORE_SAFE
if (m_resourceReferenceCount > 0)
@@ -35,7 +36,11 @@ void NzResource::AddResourceListener(NzResourceListener* listener, int index) co
NazaraLock(m_mutex)
if (!m_resourceListenersLocked)
m_resourceListeners.insert(std::make_pair(listener, index));
{
auto pair = m_resourceListeners.insert(std::make_pair(listener, std::make_pair(index, 1U)));
if (!pair.second)
pair.first->second.second++;
}
}
void NzResource::AddResourceReference() const
@@ -59,7 +64,11 @@ void NzResource::RemoveResourceListener(NzResourceListener* listener) const
NazaraLock(m_mutex);
if (!m_resourceListenersLocked)
m_resourceListeners.erase(listener);
{
ResourceListenerMap::iterator it = m_resourceListeners.find(listener);
if (it != m_resourceListeners.end())
RemoveResourceListenerIterator(it);
}
}
bool NzResource::RemoveResourceReference() const
@@ -105,8 +114,9 @@ void NzResource::NotifyCreated()
auto it = m_resourceListeners.begin();
while (it != m_resourceListeners.end())
{
if (!it->first->OnResourceCreated(this, it->second))
m_resourceListeners.erase(it++);
ResourceListenerMap::iterator iterator = it++;
if (!it->first->OnResourceCreated(this, it->second.first))
RemoveResourceListenerIterator(it++);
else
++it;
}
@@ -123,11 +133,20 @@ void NzResource::NotifyDestroy()
auto it = m_resourceListeners.begin();
while (it != m_resourceListeners.end())
{
if (!it->first->OnResourceDestroy(this, it->second))
m_resourceListeners.erase(it++);
if (!it->first->OnResourceDestroy(this, it->second.first))
RemoveResourceListenerIterator(it++);
else
++it;
}
m_resourceListenersLocked = false;
}
void NzResource::RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const
{
unsigned int& referenceCount = iterator->second.second;
if (referenceCount == 1)
m_resourceListeners.erase(iterator);
else
referenceCount--;
}