Add generic handlers

Former-commit-id: 8fc343d3a056de8031cf453748b8801d50d3710e
This commit is contained in:
Lynix
2016-03-31 21:14:22 +02:00
parent a2f6e54104
commit a77ad42fcb
16 changed files with 542 additions and 423 deletions

View File

@@ -0,0 +1,47 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
#pragma once
#ifndef NAZARA_OBJECTHANDLER_HPP
#define NAZARA_OBJECTHANDLER_HPP
#include <Nazara/Core/Bitset.hpp>
#include <memory>
#include <vector>
namespace Nz
{
template<typename T> class ObjectHandle;
template<typename T>
class HandledObject
{
friend ObjectHandle<T>;
public:
HandledObject() = default;
HandledObject(const HandledObject& object);
HandledObject(HandledObject&& object);
~HandledObject();
ObjectHandle<T> CreateHandle();
HandledObject& operator=(const HandledObject& object);
HandledObject& operator=(HandledObject&& object);
protected:
void UnregisterAllHandles();
private:
void RegisterHandle(ObjectHandle<T>* handle);
void UnregisterHandle(ObjectHandle<T>* handle);
std::vector<ObjectHandle<T>*> m_handles;
};
}
#include <Nazara/Core/HandledObject.inl>
#endif // NAZARA_OBJECTHANDLER_HPP

View File

@@ -0,0 +1,84 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ObjectHandle.hpp>
#include <algorithm>
#include <type_traits>
#include <utility>
namespace Nz
{
template<typename T>
HandledObject<T>::HandledObject(const HandledObject& object)
{
// Don't copy anything, we're a copy of the object, we have no handle right now
}
template<typename T>
HandledObject<T>::HandledObject(HandledObject&& object) :
m_handles(std::move(object.m_handles))
{
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this));
}
template<typename T>
HandledObject<T>::~HandledObject()
{
UnregisterAllHandles();
}
template<typename T>
ObjectHandle<T> HandledObject<T>::CreateHandle()
{
return ObjectHandle<T>(static_cast<T*>(this));
}
template<typename T>
HandledObject<T>& HandledObject<T>::operator=(const HandledObject& object)
{
// Nothing to do
return *this;
}
template<typename T>
HandledObject<T>& HandledObject<T>::operator=(HandledObject&& object)
{
m_handles = std::move(object.m_handles);
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this));
return *this;
}
template<typename T>
void HandledObject<T>::RegisterHandle(ObjectHandle<T>* handle)
{
///DOC: Un handle ne doit être enregistré qu'une fois, des erreurs se produisent s'il l'est plus d'une fois
m_handles.push_back(handle);
}
template<typename T>
void HandledObject<T>::UnregisterAllHandles()
{
// Tell every handle we got destroyed, to null them
for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectDestroyed();
m_handles.clear();
}
template<typename T>
void HandledObject<T>::UnregisterHandle(ObjectHandle<T>* handle)
{
///DOC: Un handle ne doit être libéré qu'une fois, et doit faire partie de la liste, sous peine de crash
auto it = std::find(m_handles.begin(), m_handles.end(), handle);
NazaraAssert(it != m_handles.end(), "Handle not registred");
// On échange cet élément avec le dernier, et on diminue la taille du vector de 1
std::swap(*it, m_handles.back());
m_handles.pop_back();
}
}

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2015 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_OBJECTHANDLE_HPP
#define NAZARA_OBJECTHANDLE_HPP
#include <Nazara/Core/Algorithm.hpp>
#include <ostream>
namespace Nz
{
template<typename T> class HandledObject;
template<typename T>
class ObjectHandle
{
friend HandledObject<T>;
public:
ObjectHandle();
explicit ObjectHandle(T* object);
ObjectHandle(const ObjectHandle& handle);
~ObjectHandle();
T* GetObject() const;
bool IsValid() const;
void Reset(T* object = nullptr);
void Reset(const ObjectHandle& handle);
ObjectHandle& Swap(ObjectHandle& handle);
Nz::String ToString() const;
operator bool() const;
operator T*() const;
T* operator->() const;
ObjectHandle& operator=(T* object);
ObjectHandle& operator=(const ObjectHandle& handle);
static const ObjectHandle InvalidHandle;
protected:
void OnObjectDestroyed();
void OnObjectMoved(T* newObject);
T* m_object;
};
template<typename T> std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle);
template<typename T> bool operator==(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator==(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator==(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator!=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator!=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator!=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator<(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator<(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator<=(const ObjectHandle<T>, const ObjectHandle<T>& rhs);
template<typename T> bool operator<=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator<=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator>(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> struct PointedType<ObjectHandle<T>> { typedef T type; };
template<typename T> struct PointedType<const ObjectHandle<T>> { typedef T type; };
}
namespace std
{
template<typename T>
void swap(Nz::ObjectHandle<T>& lhs, Nz::ObjectHandle<T>& rhs);
}
#include <Nazara/Core/ObjectHandle.inl>
#endif // NAZARA_OBJECTHANDLE_HPP

View File

@@ -0,0 +1,280 @@
// Copyright (C) 2015 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
#include <Nazara/Core/ObjectHandle.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <functional>
#include <limits>
namespace Nz
{
template<typename T>
ObjectHandle<T>::ObjectHandle() :
m_object(nullptr)
{
}
template<typename T>
ObjectHandle<T>::ObjectHandle(T* object) :
ObjectHandle()
{
Reset(object);
}
template<typename T>
ObjectHandle<T>::ObjectHandle(const ObjectHandle<T>& handle) :
ObjectHandle()
{
Reset(handle);
}
template<typename T>
ObjectHandle<T>::~ObjectHandle()
{
Reset(nullptr);
}
template<typename T>
T* ObjectHandle<T>::GetObject() const
{
return m_object;
}
template<typename T>
bool ObjectHandle<T>::IsValid() const
{
return m_object != nullptr;
}
template<typename T>
void ObjectHandle<T>::Reset(T* object)
{
// Si nous avions déjà une entité, nous devons l'informer que nous ne pointons plus sur elle
if (m_object)
m_object->UnregisterHandle(this);
m_object = object;
if (m_object)
// On informe la nouvelle entité que nous pointons sur elle
m_object->RegisterHandle(this);
}
template<typename T>
void ObjectHandle<T>::Reset(const ObjectHandle<T>& handle)
{
Reset(handle.GetObject());
}
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::Swap(ObjectHandle<T>& handle)
{
// Comme nous inversons les handles, nous devons prévenir les entités
// La version par défaut de swap (à base de move) aurait fonctionné,
// mais en enregistrant les handles une fois de plus que nécessaire (à cause de la copie temporaire).
if (m_object)
{
m_object->UnregisterHandle(this);
m_object->RegisterHandle(&handle);
}
if (handle.m_object)
{
handle.m_object->UnregisterHandle(&handle);
handle.m_object->RegisterHandle(this);
}
// On effectue l'échange
std::swap(m_object, handle.m_object);
return *this;
}
template<typename T>
Nz::String ObjectHandle<T>::ToString() const
{
Nz::StringStream ss;
ss << "ObjectHandle(";
if (IsValid())
ss << m_object->ToString();
else
ss << "Null";
ss << ')';
return ss;
}
template<typename T>
ObjectHandle<T>::operator bool() const
{
return IsValid();
}
template<typename T>
ObjectHandle<T>::operator T*() const
{
return m_object;
}
template<typename T>
T* ObjectHandle<T>::operator->() const
{
return m_object;
}
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::operator=(T* entity)
{
Reset(entity);
return *this;
}
template<typename T>
ObjectHandle<T>& ObjectHandle<T>::operator=(const ObjectHandle<T>& handle)
{
Reset(handle);
return *this;
}
template<typename T>
void ObjectHandle<T>::OnObjectDestroyed()
{
// Shortcut
m_object = nullptr;
}
template<typename T>
void ObjectHandle<T>::OnObjectMoved(T* newObject)
{
// The object has been moved, update our pointer
m_object = newObject;
}
template<typename T>
std::ostream& operator<<(std::ostream& out, const ObjectHandle<T>& handle)
{
return handle.ToString();
}
template<typename T>
bool operator==(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return lhs.GetObject() == rhs.GetObject();
}
template<typename T>
bool operator==(const T& lhs, const ObjectHandle<T>& rhs)
{
return &lhs == rhs.GetObject();
}
template<typename T>
bool operator==(const ObjectHandle<T>& lhs, const T& rhs)
{
return lhs.GetObject() == &rhs;
}
template<typename T>
bool operator!=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs == rhs);
}
template<typename T>
bool operator!=(const T& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs == rhs);
}
template<typename T>
bool operator!=(const ObjectHandle<T>& lhs, const T& rhs)
{
return !(lhs == rhs);
}
template<typename T>
bool operator<(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return lhs.m_object < rhs.m_object;
}
template<typename T>
bool operator<(const T& lhs, const ObjectHandle<T>& rhs)
{
return &lhs < rhs.m_object;
}
template<typename T>
bool operator<(const ObjectHandle<T>& lhs, const T& rhs)
{
return lhs.m_object < &rhs;
}
template<typename T>
bool operator<=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs > rhs);
}
template<typename T>
bool operator<=(const T& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs > rhs);
}
template<typename T>
bool operator<=(const ObjectHandle<T>& lhs, const T& rhs)
{
return !(lhs > rhs);
}
template<typename T>
bool operator>(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return rhs < lhs;
}
template<typename T>
bool operator>(const T& lhs, const ObjectHandle<T>& rhs)
{
return rhs < lhs;
}
template<typename T>
bool operator>(const ObjectHandle<T>& lhs, const T& rhs)
{
return rhs < lhs;
}
template<typename T>
bool operator>=(const ObjectHandle<T>& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs < rhs);
}
template<typename T>
bool operator>=(const T& lhs, const ObjectHandle<T>& rhs)
{
return !(lhs < rhs);
}
template<typename T>
bool operator>=(const ObjectHandle<T>& lhs, const T& rhs)
{
return !(lhs < rhs);
}
template<typename T>
const ObjectHandle<T> ObjectHandle<T>::InvalidHandle;
}
namespace std
{
template<typename T>
void swap(Nz::ObjectHandle<T>& lhs, Nz::ObjectHandle<T>& rhs)
{
lhs.Swap(rhs);
}
}