SHADE_Y3/SHADE_Engine/src/Resource/Handle.h

222 lines
10 KiB
C
Raw Normal View History

2022-09-08 19:11:25 +08:00
#pragma once
#include <stdexcept>
#include <limits>
namespace SHADE
{
/*---------------------------------------------------------------------------------*/
/* Forward Declarations */
/*---------------------------------------------------------------------------------*/
template<typename T>
class ResourceLibrary;
2022-09-17 23:32:29 +08:00
2022-09-08 19:11:25 +08:00
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// Exception thrown when an invalid Handle was dereferenced.
/// </summary>
class InvalidHandleException : std::runtime_error
{
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
using std::runtime_error::runtime_error;
};
/// <summary>
/// Base implementation of the Handle that is not templated to allow for holding
/// generic non-type-specific Handles.
/// </summary>
class HandleBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Native ID type of a handle
/// </summary>
union Id
{
/*-------------------------------------------------------------------------*/
/* Data */
/*-------------------------------------------------------------------------*/
uint64_t Raw = std::numeric_limits<uint64_t>::max();
struct
{
uint32_t Index;
uint32_t Version;
} Data;
};
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
inline Id GetId() const;
/*-----------------------------------------------------------------------------*/
/* Overloaded Operators */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Converts to true if this is a valid Handle.
/// </summary>
inline operator bool() const;
protected:
/*-----------------------------------------------------------------------------*/
/* Constants */
/*-----------------------------------------------------------------------------*/
static constexpr Id INVALID_ID {};
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Id id = INVALID_ID;
};
/// <summary>
/// Generic implementation of a Handle object
/// </summary>
/// <typeparam name="T">Type of the handle.</typeparam>
template<typename T>
class Handle : public HandleBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
Handle() = default;
~Handle() = default;
2022-09-17 23:32:29 +08:00
2022-09-08 19:11:25 +08:00
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Deallocates the object pointed to by this function.
/// </summary>
void Free();
/*-----------------------------------------------------------------------------*/
/* Overloaded Operators */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Returns the underlying object pointed to by the Handle.
/// </summary>
/// <exception cref="InvalidHandleException">
/// Thrown when this is an Invalid Handle.
/// </exception>
/// <returns>Reference to the object pointed to by this Handle.</returns>
T& operator*();
/// <summary>
/// Returns the underlying object pointed to by the Handle as read-only.
/// </summary>
/// <exception cref="InvalidHandleException">
/// Thrown when this is an Invalid Handle.
/// </exception>
/// <returns>Const reference to the object pointed to by this Handle.</returns>
const T& operator*() const;
/// <summary>
/// Provides access to members of the underlying object pointed to by the Handle.
/// </summary>
/// <exception cref="InvalidHandleException">
/// Thrown when this is an Invalid Handle.
/// </exception>
/// <returns>Pointer to the object pointed to by this Handle.</returns>
T* operator->();
/// <summary>
/// Provides read-only access to members of the underlying object pointed to by
/// the Handle.
/// </summary>
/// <exception cref="InvalidHandleException">
/// Thrown when this is an Invalid Handle.
/// </exception>
/// <returns>Const pointer to the object pointed to by this Handle.</returns>
const T* operator->() const;
protected:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
ResourceLibrary<T>* library = nullptr;
2022-09-08 19:11:25 +08:00
/*-----------------------------------------------------------------------------*/
/* Friend Declarations */
/*-----------------------------------------------------------------------------*/
friend class ResourceLibrary<T>;
};
/// <summary>
/// Interface that needs to be implemented by classes that want to store a Handle to
/// themselves after construction by Resource Managers.
/// </summary>
template<typename T>
class ISelfHandle
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructors */
/*-----------------------------------------------------------------------------*/
ISelfHandle() = default;
ISelfHandle(const ISelfHandle& rhs);
ISelfHandle(ISelfHandle&& rhs);
/*-----------------------------------------------------------------------------*/
/* Overloaded Operators */
/*-----------------------------------------------------------------------------*/
ISelfHandle& operator=(const ISelfHandle& rhs);
ISelfHandle& operator=(ISelfHandle&& rhs);
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Retrieves the Handle of this object.
/// </summary>
/// <returns>Handle to this object.</returns>
Handle<T> GetHandle() const;
/// <summary>
/// Used to set the Handle for this object. Should only be used by
/// ResourceLibrary.
/// </summary>
/// <param name="rscLib">Required to lock usage to ResourceLibrary only.</param>
/// <param name="hdl">Handle to set.</param>
void SetHandle(const ResourceLibrary<T>& rscLib, Handle<T> hdl);
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
Handle<T> handle;
};
}
namespace std
{
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
/*---------------------------------------------------------------------------------*/
/// <summary>
/// std::hash template specialization for Handle<T>
/// </summary>
/// <typeparam name="T">Type for the Handle.</typeparam>
template<typename T>
struct hash<SHADE::Handle<T>>
{
std::size_t operator() (const SHADE::Handle<T>& hdl) const;
};
/// <summary>
/// std::hash template specialization for std::pair<Handle<T1>, Handle<T2>>
/// </summary>
/// <typeparam name="T">Type for the first Handle.</typeparam>
/// <typeparam name="T">Type for the second Handle.</typeparam>
template<typename T1, typename T2>
struct hash<std::pair<SHADE::Handle<T1>, SHADE::Handle<T2>>>
{
std::size_t operator() (std::pair<SHADE::Handle<T1>, SHADE::Handle<T2>> const& pair) const;
};
2022-09-08 19:11:25 +08:00
}
#include "Handle.hpp"