Improved ResourceListeners

Former-commit-id: 8016c23cb75aab94762a1e2838dbbcac2093119b
This commit is contained in:
Lynix 2013-08-09 16:28:07 +02:00
parent 4b1a6cc09e
commit d4cff9946e
11 changed files with 74 additions and 71 deletions

View File

@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <atomic>
#include <set>
#include <unordered_map>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
#include <Nazara/Core/ThreadSafety.hpp>
@ -19,23 +19,6 @@
class NzResourceListener;
struct NzResourceEntry
{
NzResourceEntry(NzResourceListener* resourceListener, int i = 0) :
listener(resourceListener),
index(i)
{
}
bool operator<(const NzResourceEntry& rhs) const
{
return listener < rhs.listener;
}
NzResourceListener* listener;
int index;
};
class NAZARA_API NzResource
{
public:
@ -59,16 +42,13 @@ class NAZARA_API NzResource
void NotifyDestroy();
private:
void EnsureResourceListenerUpdate() const;
NazaraMutexAttrib(m_mutex, mutable)
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
mutable std::set<NzResourceEntry> m_resourceListeners;
mutable std::set<NzResourceEntry> m_resourceListenersCache;
mutable bool m_resourceListenerUpdated;
mutable std::unordered_map<NzResourceListener*, int> m_resourceListeners;
std::atomic_bool m_resourcePersistent;
mutable std::atomic_uint m_resourceReferenceCount;
bool m_resourceListenersLocked;
};
#endif // NAZARA_RESOURCE_HPP

View File

@ -17,8 +17,8 @@ class NAZARA_API NzResourceListener
NzResourceListener() = default;
virtual ~NzResourceListener();
virtual void OnResourceCreated(const NzResource* resource, int index);
virtual void OnResourceDestroy(const NzResource* resource, int index);
virtual bool OnResourceCreated(const NzResource* resource, int index);
virtual bool OnResourceDestroy(const NzResource* resource, int index);
virtual void OnResourceReleased(const NzResource* resource, int index);
};

View File

@ -38,7 +38,7 @@ class NAZARA_API NzForwardRenderQueue : public NzAbstractRenderQueue, NzResource
void Sort(const NzCamera& camera);
private:
void OnResourceDestroy(const NzResource* resource, int index);
bool OnResourceDestroy(const NzResource* resource, int index) override;
struct ModelMaterialComparator
{

View File

@ -51,7 +51,7 @@ class NAZARA_API NzRenderTexture : public NzRenderTarget, NzResourceListener, Nz
void Desactivate() const override;
private:
void OnResourceDestroy(const NzResource* resource, int index) override;
bool OnResourceDestroy(const NzResource* resource, int index) override;
NzRenderTextureImpl* m_impl = nullptr;
};

View File

@ -12,15 +12,16 @@
NzResource::NzResource(bool persistent) :
m_resourcePersistent(persistent),
m_resourceReferenceCount(0)
m_resourceReferenceCount(0),
m_resourceListenersLocked(false)
{
}
NzResource::~NzResource()
{
EnsureResourceListenerUpdate();
for (const NzResourceEntry& entry : m_resourceListenersCache)
entry.listener->OnResourceReleased(this, entry.index);
m_resourceListenersLocked = true;
for (auto& pair : m_resourceListeners)
pair.first->OnResourceReleased(this, pair.second);
#if NAZARA_CORE_SAFE
if (m_resourceReferenceCount > 0)
@ -30,10 +31,11 @@ NzResource::~NzResource()
void NzResource::AddResourceListener(NzResourceListener* listener, int index) const
{
///DOC: Est ignoré si appelé depuis un évènement
NazaraLock(m_mutex)
if (m_resourceListeners.insert(NzResourceEntry(listener, index)).second)
m_resourceListenerUpdated = false;
if (!m_resourceListenersLocked)
m_resourceListeners.insert(std::make_pair(listener, index));
}
void NzResource::AddResourceReference() const
@ -53,10 +55,11 @@ bool NzResource::IsPersistent() const
void NzResource::RemoveResourceListener(NzResourceListener* listener) const
{
NazaraMutexLock(m_mutex);
///DOC: Est ignoré si appelé depuis un évènement
NazaraLock(m_mutex);
if (m_resourceListeners.erase(listener) != 0)
m_resourceListenerUpdated = false;
if (!m_resourceListenersLocked)
m_resourceListeners.erase(listener);
}
bool NzResource::RemoveResourceReference() const
@ -97,26 +100,34 @@ void NzResource::NotifyCreated()
{
NazaraLock(m_mutex)
EnsureResourceListenerUpdate();
for (const NzResourceEntry& entry : m_resourceListenersCache)
entry.listener->OnResourceCreated(this, entry.index);
m_resourceListenersLocked = true;
auto it = m_resourceListeners.begin();
while (it != m_resourceListeners.end())
{
if (!it->first->OnResourceCreated(this, it->second))
m_resourceListeners.erase(it++);
else
++it;
}
m_resourceListenersLocked = false;
}
void NzResource::NotifyDestroy()
{
NazaraLock(m_mutex)
EnsureResourceListenerUpdate();
for (const NzResourceEntry& entry : m_resourceListenersCache)
entry.listener->OnResourceDestroy(this, entry.index);
}
m_resourceListenersLocked = true;
void NzResource::EnsureResourceListenerUpdate() const
{
// Déjà bloqué par une mutex
if (!m_resourceListenerUpdated)
auto it = m_resourceListeners.begin();
while (it != m_resourceListeners.end())
{
m_resourceListenersCache = m_resourceListeners;
m_resourceListenerUpdated = true;
if (!it->first->OnResourceDestroy(this, it->second))
m_resourceListeners.erase(it++);
else
++it;
}
m_resourceListenersLocked = false;
}

View File

@ -7,16 +7,20 @@
NzResourceListener::~NzResourceListener() = default;
void NzResourceListener::OnResourceCreated(const NzResource* resource, int index)
bool NzResourceListener::OnResourceCreated(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
return true;
}
void NzResourceListener::OnResourceDestroy(const NzResource* resource, int index)
bool NzResourceListener::OnResourceDestroy(const NzResource* resource, int index)
{
NazaraUnused(resource);
NazaraUnused(index);
return true;
}
void NzResourceListener::OnResourceReleased(const NzResource* resource, int index)

View File

@ -206,7 +206,7 @@ void NzForwardRenderQueue::Sort(const NzCamera& camera)
std::sort(transparentsModels.begin(), transparentsModels.end(), comparator);
}
void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int index)
bool NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int index)
{
switch (index)
{
@ -231,7 +231,7 @@ void NzForwardRenderQueue::OnResourceDestroy(const NzResource* resource, int ind
}
}
resource->RemoveResourceListener(this);
return false; // Nous ne voulons plus recevoir d'évènement de cette ressource
}
bool NzForwardRenderQueue::SkeletalMeshComparator::operator()(const NzSkeletalMesh* subMesh1, const NzSkeletalMesh* subMesh2)

View File

@ -520,7 +520,7 @@ bool NzGLSLProgram::SendVector(int location, const NzVector4f& vector)
return true;
}
void NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
bool NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
{
NazaraUnused(resource);
@ -530,7 +530,7 @@ void NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
if (it == m_textures.end())
{
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
return;
return false;
}
#endif
@ -540,15 +540,17 @@ void NzGLSLProgram::OnResourceCreated(const NzResource* resource, int index)
if (slot.texture != resource)
{
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
return;
return false;
}
#endif
slot.enabled = true;
slot.updated = false;
return true;
}
void NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
bool NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
{
NazaraUnused(resource);
@ -558,7 +560,7 @@ void NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
if (it == m_textures.end())
{
NazaraInternalError("Invalid index (" + NzString::Number(index) + ')');
return;
return false;
}
#endif
@ -568,19 +570,19 @@ void NzGLSLProgram::OnResourceDestroy(const NzResource* resource, int index)
if (slot.texture != resource)
{
NazaraInternalError("Wrong texture at location #" + NzString::Number(index));
return;
return false;
}
#endif
slot.enabled = false;
return true;
}
void NzGLSLProgram::OnResourceReleased(const NzResource* resource, int index)
{
if (m_textures.erase(index) == 0)
NazaraInternalError("Texture " + NzString::Pointer(resource) + " not found");
resource->RemoveResourceListener(this);
}
void NzGLSLProgram::PreLinkage()

View File

@ -60,8 +60,8 @@ class NzGLSLProgram : public NzAbstractShaderProgram, NzResourceListener
bool SendVector(int location, const NzVector4f& vector);
private:
void OnResourceCreated(const NzResource* resource, int index) override;
void OnResourceDestroy(const NzResource* resource, int index) override;
bool OnResourceCreated(const NzResource* resource, int index) override;
bool OnResourceDestroy(const NzResource* resource, int index) override;
void OnResourceReleased(const NzResource* resource, int index) override;
void PreLinkage();
bool PostLinkage();

View File

@ -324,11 +324,12 @@ void NzRenderTexture::Destroy()
{
if (m_impl)
{
bool canFreeFBO = true;
#if NAZARA_RENDERER_SAFE
if (NzContext::GetCurrent() != m_impl->context)
{
NazaraError("RenderTexture can only be used with it's creation context");
return;
NazaraWarning("RenderTexture should be destroyed by it's creation context, this will cause leaks");
canFreeFBO = false;
}
#endif
@ -339,7 +340,7 @@ void NzRenderTexture::Destroy()
if (attachment.isUsed)
{
if (attachment.isBuffer)
glDeleteRenderbuffers(1, &attachment.buffer);
glDeleteRenderbuffers(1, &attachment.buffer); // Les Renderbuffers sont partagés entre les contextes: Ne posera pas de problème
else
{
attachment.texture->SetRenderTexture(nullptr);
@ -348,7 +349,8 @@ void NzRenderTexture::Destroy()
}
}
glDeleteFramebuffers(1, &m_impl->fbo);
if (canFreeFBO)
glDeleteFramebuffers(1, &m_impl->fbo);
delete m_impl;
m_impl = nullptr;
@ -636,11 +638,15 @@ void NzRenderTexture::Desactivate() const
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
void NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
bool NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
{
if (resource == m_impl->context)
// Notre context a été détruit, libérons la RenderTexture pour éviter un leak
{
// Notre contexte va être détruit, libérons la RenderTexture pour éviter un leak
Destroy();
return false;
}
else
{
// Sinon, c'est une texture
@ -652,5 +658,7 @@ void NzRenderTexture::OnResourceDestroy(const NzResource* resource, int index)
m_impl->checked = false;
m_impl->drawBuffersUpdated = false;
return true;
}
}

View File

@ -128,6 +128,4 @@ void NzStaticMesh::OnResourceReleased(const NzResource* resource, int index)
m_vertexBuffer = nullptr;
else
NazaraInternalError("Not listening to " + NzString::Pointer(resource));
resource->RemoveResourceListener(this);
}