Separated reference counting from Resources

Former-commit-id: 7380818cfee9e249c11fd15da9ff7883a6e76565
This commit is contained in:
Lynix
2014-07-15 00:59:02 +02:00
parent 0af8bc4829
commit 9e04e8a0e4
51 changed files with 566 additions and 508 deletions

View File

@@ -62,7 +62,7 @@
#define NAZARA_THREADSAFETY_DYNLIB 1 // NzDynLib
#define NAZARA_THREADSAFETY_FILE 1 // NzFile
#define NAZARA_THREADSAFETY_LOG 1 // NzLog
#define NAZARA_THREADSAFETY_RESOURCE 1 // NzResource
#define NAZARA_THREADSAFETY_REFCOUNTED 1 // NzRefCounted
// Le nombre de spinlocks à utiliser avec les sections critiques de Windows (0 pour désactiver)
#define NAZARA_CORE_WINDOWS_CS_SPINLOCKS 4096

View File

@@ -0,0 +1,26 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_OBJECTLISTENER_HPP
#define NAZARA_OBJECTLISTENER_HPP
#include <Nazara/Prerequesites.hpp>
class NzRefCounted;
class NAZARA_API NzObjectListener
{
public:
NzObjectListener() = default;
virtual ~NzObjectListener();
virtual bool OnObjectCreated(const NzRefCounted* object, int index);
virtual bool OnObjectDestroy(const NzRefCounted* object, int index);
virtual bool OnObjectModified(const NzRefCounted* object, int index, unsigned int code);
virtual void OnObjectReleased(const NzRefCounted* object, int index);
};
#endif // NAZARA_OBJECTLISTENER_HPP

View File

@@ -8,38 +8,38 @@
#define NAZARA_RESOURCEREF_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/RefCounted.hpp>
#include <type_traits>
template<typename T>
class NzResourceRef
class NzObjectRef
{
static_assert(std::is_base_of<NzResource, T>::value, "ResourceRef should only be used with resource type");
static_assert(std::is_base_of<NzRefCounted, T>::value, "ObjectRef shall only be used with RefCounted-derived type");
public:
NzResourceRef();
NzResourceRef(T* resource);
NzResourceRef(const NzResourceRef& ref);
NzResourceRef(NzResourceRef&& ref) noexcept;
~NzResourceRef();
NzObjectRef();
NzObjectRef(T* resource);
NzObjectRef(const NzObjectRef& ref);
NzObjectRef(NzObjectRef&& ref) noexcept;
~NzObjectRef();
bool IsValid() const;
T* Release();
bool Reset(T* resource = nullptr);
NzResourceRef& Swap(NzResourceRef& ref);
NzObjectRef& Swap(NzObjectRef& ref);
operator bool() const;
operator T*() const;
T* operator->() const;
NzResourceRef& operator=(T* resource);
NzResourceRef& operator=(const NzResourceRef& ref);
NzResourceRef& operator=(NzResourceRef&& ref) noexcept;
NzObjectRef& operator=(T* resource);
NzObjectRef& operator=(const NzObjectRef& ref);
NzObjectRef& operator=(NzObjectRef&& ref) noexcept;
private:
T* m_resource;
};
#include <Nazara/Core/ResourceRef.inl>
#include <Nazara/Core/ObjectRef.inl>
#endif // NAZARA_RESOURCEREF_HPP

View File

@@ -6,49 +6,49 @@
#include <Nazara/Core/Debug.hpp>
template<typename T>
NzResourceRef<T>::NzResourceRef() :
NzObjectRef<T>::NzObjectRef() :
m_resource(nullptr)
{
}
template<typename T>
NzResourceRef<T>::NzResourceRef(T* resource) :
NzObjectRef<T>::NzObjectRef(T* resource) :
m_resource(resource)
{
if (m_resource)
m_resource->AddResourceReference();
m_resource->AddReference();
}
template<typename T>
NzResourceRef<T>::NzResourceRef(const NzResourceRef& ref) :
NzObjectRef<T>::NzObjectRef(const NzObjectRef& ref) :
m_resource(ref.m_resource)
{
if (m_resource)
m_resource->AddResourceReference();
m_resource->AddReference();
}
template<typename T>
NzResourceRef<T>::NzResourceRef(NzResourceRef&& ref) noexcept :
NzObjectRef<T>::NzObjectRef(NzObjectRef&& ref) noexcept :
m_resource(ref.m_resource)
{
ref.m_resource = nullptr; // On vole la référence
}
template<typename T>
NzResourceRef<T>::~NzResourceRef()
NzObjectRef<T>::~NzObjectRef()
{
if (m_resource)
m_resource->RemoveResourceReference();
m_resource->RemoveReference();
}
template<typename T>
bool NzResourceRef<T>::IsValid() const
bool NzObjectRef<T>::IsValid() const
{
return m_resource != nullptr;
}
template<typename T>
T* NzResourceRef<T>::Release()
T* NzObjectRef<T>::Release()
{
T* resource = m_resource;
m_resource = nullptr;
@@ -57,27 +57,27 @@ T* NzResourceRef<T>::Release()
}
template<typename T>
bool NzResourceRef<T>::Reset(T* resource)
bool NzObjectRef<T>::Reset(T* resource)
{
bool destroyed = false;
if (m_resource != resource)
{
if (m_resource)
{
destroyed = m_resource->RemoveResourceReference();
destroyed = m_resource->RemoveReference();
m_resource = nullptr;
}
m_resource = resource;
if (m_resource)
m_resource->AddResourceReference();
m_resource->AddReference();
}
return destroyed;
}
template<typename T>
NzResourceRef<T>& NzResourceRef<T>::Swap(NzResourceRef& ref)
NzObjectRef<T>& NzObjectRef<T>::Swap(NzObjectRef& ref)
{
std::swap(m_resource, ref.m_resource);
@@ -85,25 +85,25 @@ NzResourceRef<T>& NzResourceRef<T>::Swap(NzResourceRef& ref)
}
template<typename T>
NzResourceRef<T>::operator bool() const
NzObjectRef<T>::operator bool() const
{
return IsValid();
}
template<typename T>
NzResourceRef<T>::operator T*() const
NzObjectRef<T>::operator T*() const
{
return m_resource;
}
template<typename T>
T* NzResourceRef<T>::operator->() const
T* NzObjectRef<T>::operator->() const
{
return m_resource;
}
template<typename T>
NzResourceRef<T>& NzResourceRef<T>::operator=(T* resource)
NzObjectRef<T>& NzObjectRef<T>::operator=(T* resource)
{
Reset(resource);
@@ -111,7 +111,7 @@ NzResourceRef<T>& NzResourceRef<T>::operator=(T* resource)
}
template<typename T>
NzResourceRef<T>& NzResourceRef<T>::operator=(const NzResourceRef& ref)
NzObjectRef<T>& NzObjectRef<T>::operator=(const NzObjectRef& ref)
{
Reset(ref.m_resource);
@@ -119,7 +119,7 @@ NzResourceRef<T>& NzResourceRef<T>::operator=(const NzResourceRef& ref)
}
template<typename T>
NzResourceRef<T>& NzResourceRef<T>::operator=(NzResourceRef&& ref) noexcept
NzObjectRef<T>& NzObjectRef<T>::operator=(NzObjectRef&& ref) noexcept
{
Reset();

View File

@@ -0,0 +1,58 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_REFCOUNTED_HPP
#define NAZARA_REFCOUNTED_HPP
#include <Nazara/Prerequesites.hpp>
#include <atomic>
#include <unordered_map>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_REFCOUNTED
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
class NzObjectListener;
class NAZARA_API NzRefCounted
{
public:
NzRefCounted(bool persistent = true);
virtual ~NzRefCounted();
void AddObjectListener(NzObjectListener* listener, int index = 0) const;
void AddReference() const;
unsigned int GetReferenceCount() const;
bool IsPersistent() const;
void RemoveObjectListener(NzObjectListener* listener) const;
bool RemoveReference() const;
bool SetPersistent(bool persistent = true, bool checkReferenceCount = false);
protected:
void NotifyCreated();
void NotifyDestroy();
void NotifyModified(unsigned int code);
private:
using ObjectListenerMap = std::unordered_map<NzObjectListener*, std::pair<int, unsigned int>>;
void RemoveObjectListenerIterator(ObjectListenerMap::iterator iterator) const;
NazaraMutexAttrib(m_mutex, mutable)
mutable ObjectListenerMap m_objectListeners;
std::atomic_bool m_persistent;
mutable std::atomic_uint m_referenceCount;
bool m_objectListenersLocked;
};
#endif // NAZARA_RESOURCE_HPP

View File

@@ -8,52 +8,20 @@
#define NAZARA_RESOURCE_HPP
#include <Nazara/Prerequesites.hpp>
#include <atomic>
#include <unordered_map>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_RESOURCE
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
class NzResourceListener;
#include <Nazara/Core/String.hpp>
class NAZARA_API NzResource
{
public:
NzResource(bool persistent = true);
NzResource() = default;
virtual ~NzResource();
void AddResourceListener(NzResourceListener* listener, int index = 0) const;
void AddResourceReference() const;
NzString GetFilePath() const;
unsigned int GetResourceReferenceCount() const;
bool IsPersistent() const;
void RemoveResourceListener(NzResourceListener* listener) const;
bool RemoveResourceReference() const;
bool SetPersistent(bool persistent = true, bool checkReferenceCount = false);
protected:
void NotifyCreated();
void NotifyDestroy();
void NotifyModified(unsigned int code);
void SetFilePath(const NzString& filePath);
private:
using ResourceListenerMap = std::unordered_map<NzResourceListener*, std::pair<int, unsigned int>>;
void RemoveResourceListenerIterator(ResourceListenerMap::iterator iterator) const;
NazaraMutexAttrib(m_mutex, mutable)
// Je fais précéder le nom par 'resource' pour éviter les éventuels conflits de noms
mutable ResourceListenerMap m_resourceListeners;
std::atomic_bool m_resourcePersistent;
mutable std::atomic_uint m_resourceReferenceCount;
bool m_resourceListenersLocked;
NzString m_filePath;
};
#endif // NAZARA_RESOURCE_HPP

View File

@@ -1,26 +0,0 @@
// Copyright (C) 2014 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RESOURCELISTENER_HPP
#define NAZARA_RESOURCELISTENER_HPP
#include <Nazara/Prerequesites.hpp>
class NzResource;
class NAZARA_API NzResourceListener
{
public:
NzResourceListener() = default;
virtual ~NzResourceListener();
virtual bool OnResourceCreated(const NzResource* resource, int index);
virtual bool OnResourceDestroy(const NzResource* resource, int index);
virtual bool OnResourceModified(const NzResource* resource, int index, unsigned int code);
virtual void OnResourceReleased(const NzResource* resource, int index);
};
#endif // NAZARA_RESOURCELISTENER_HPP

View File

@@ -8,9 +8,11 @@
#define NAZARA_RESOURCELOADER_HPP
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/String.hpp>
#include <list>
#include <tuple>
#include <type_traits>
class NzInputStream;

View File

@@ -84,7 +84,10 @@ bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzSt
}
if (fileLoader(resource, filePath, parameters))
{
resource->SetFilePath(filePath);
return true;
}
}
else
{
@@ -99,7 +102,10 @@ bool NzResourceLoader<Type, Parameters>::LoadFromFile(Type* resource, const NzSt
file.SetCursorPos(0);
if (streamLoader(resource, file, parameters))
{
resource->SetFilePath(filePath);
return true;
}
}
if (recognized == nzTernary_True)