|
|
|
@ -6,14 +6,26 @@
|
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
|
|
namespace mem
|
|
|
|
|
{ template<typename T>
|
|
|
|
|
{
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct aligned_ptr_handle
|
|
|
|
|
{
|
|
|
|
|
constexpr inline aligned_ptr_handle(){};
|
|
|
|
|
constexpr inline ~aligned_ptr_handle(){};
|
|
|
|
|
|
|
|
|
|
constexpr static inline void delete_object(T** ptr) { (*ptr)->~T(); }
|
|
|
|
|
};
|
|
|
|
|
template<typename T, typename H = aligned_ptr_handle<T > >
|
|
|
|
|
struct aligned_ptr;
|
|
|
|
|
template<>
|
|
|
|
|
struct aligned_ptr<void>;
|
|
|
|
|
using aligned_ptr_util = aligned_ptr<void>;
|
|
|
|
|
struct aligned_ptr<void, void>;
|
|
|
|
|
|
|
|
|
|
using aligned_ptr_util = aligned_ptr<void, void>;
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct aligned_ptr<void> final
|
|
|
|
|
struct aligned_ptr<void, void> final
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
static inline T* alloc(T&& value)
|
|
|
|
|
{
|
|
|
|
@ -29,24 +41,26 @@ namespace mem
|
|
|
|
|
template<typename T, typename... Args>
|
|
|
|
|
static inline T* make(Args&&... init) { return alloc(T(std::forward<Args>(init)...)); }
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
static inline void dealloc(T* ptr) { ptr->~T(); _dealloc(reinterpret_cast<void*>(ptr)); }
|
|
|
|
|
template<typename T, typename H>
|
|
|
|
|
static inline void dealloc(T* ptr) { H::delete_object(&ptr); if(ptr) _dealloc(reinterpret_cast<void*>(ptr)); }
|
|
|
|
|
private:
|
|
|
|
|
static void* _alloc(usize align, usize size);
|
|
|
|
|
static void _dealloc(void* ptr);
|
|
|
|
|
constexpr inline ~aligned_ptr(){}
|
|
|
|
|
};
|
|
|
|
|
template<typename T>
|
|
|
|
|
template<typename T, typename H>
|
|
|
|
|
struct aligned_ptr final
|
|
|
|
|
{
|
|
|
|
|
using Handle = H;
|
|
|
|
|
|
|
|
|
|
inline explicit aligned_ptr(T* raw) : ptr(raw){}
|
|
|
|
|
|
|
|
|
|
inline aligned_ptr(aligned_ptr<T>&& move) : ptr(move.ptr) { *const_cast<T**>(&move.ptr) = nullptr; }
|
|
|
|
|
inline aligned_ptr(aligned_ptr<T, H>&& move) : ptr(move.ptr) { *const_cast<T**>(&move.ptr) = nullptr; }
|
|
|
|
|
|
|
|
|
|
inline aligned_ptr(T&& box) : aligned_ptr(aligned_ptr_util::alloc(std::move(box))){}
|
|
|
|
|
inline aligned_ptr() : aligned_ptr(T()){}
|
|
|
|
|
|
|
|
|
|
inline ~aligned_ptr() { if(ptr) aligned_ptr<void>::dealloc<T>(ptr); }
|
|
|
|
|
inline ~aligned_ptr() { if(ptr) aligned_ptr_util::dealloc<T, Handle>(ptr); }
|
|
|
|
|
|
|
|
|
|
inline aligned_ptr<T> clone() const { return aligned_ptr(*this); }
|
|
|
|
|
|
|
|
|
@ -65,20 +79,20 @@ namespace mem
|
|
|
|
|
inline operator const T*() const { return get_ptr(); }
|
|
|
|
|
inline operator T*() { return get_ptr(); }
|
|
|
|
|
|
|
|
|
|
inline aligned_ptr<T>& operator=(aligned_ptr<T>&& other)
|
|
|
|
|
inline aligned_ptr<T>& operator=(aligned_ptr<T, H>&& other)
|
|
|
|
|
{
|
|
|
|
|
if(ptr) aligned_ptr<void>::dealloc<T>(ptr);
|
|
|
|
|
if(ptr) aligned_ptr_util::dealloc<T, H>(ptr);
|
|
|
|
|
*const_cast<T**>(&ptr) = other.ptr;
|
|
|
|
|
*const_cast<T**>(&other.ptr) = nullptr;
|
|
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
private:
|
|
|
|
|
inline aligned_ptr<T>& operator=(const aligned_ptr<T>& other)
|
|
|
|
|
inline aligned_ptr<T>& operator=(const aligned_ptr<T, H>& other)
|
|
|
|
|
{
|
|
|
|
|
return (*this = other.clone());
|
|
|
|
|
}
|
|
|
|
|
inline aligned_ptr(const aligned_ptr<T>& copy) : ptr(aligned_ptr<void>::make<T>(copy.get())){}
|
|
|
|
|
inline aligned_ptr(const aligned_ptr<T, H>& copy) : ptr(aligned_ptr_util::make<T>(copy.get())){}
|
|
|
|
|
T* const ptr;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|