parent
5ac7fc5e11
commit
3b1628d396
@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <new>
|
||||
#include <utility>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace mem
|
||||
{ template<typename T>
|
||||
struct aligned_ptr;
|
||||
template<>
|
||||
struct aligned_ptr<void>;
|
||||
using aligned_ptr_util = aligned_ptr<void>;
|
||||
template<>
|
||||
struct aligned_ptr<void> final
|
||||
{
|
||||
template<typename T>
|
||||
static inline T* alloc(T&& value)
|
||||
{
|
||||
u8* ptr = reinterpret_cast<u8*>(_alloc(alignof(T), sizeof(T)));
|
||||
new(ptr) T(std::move(value));
|
||||
return reinterpret_cast<T*>(ptr);
|
||||
}
|
||||
template<typename T>
|
||||
static inline T* alloc()
|
||||
{
|
||||
return alloc(T());
|
||||
}
|
||||
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)); }
|
||||
private:
|
||||
static void* _alloc(usize align, usize size);
|
||||
static void _dealloc(void* ptr);
|
||||
constexpr inline ~aligned_ptr(){}
|
||||
};
|
||||
template<typename T>
|
||||
struct aligned_ptr final
|
||||
{
|
||||
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(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<T> clone() const { return aligned_ptr(*this); }
|
||||
|
||||
inline const T & get() const { if(ptr) return *ptr; else throw "TODO: moved"; }
|
||||
inline T & get() { if(ptr) return *ptr; else throw "TODO: moved"; }
|
||||
|
||||
inline const T * get_ptr() const { if(ptr) return ptr; else throw "TODO: moved"; }
|
||||
inline T * get_ptr() { if(ptr) return ptr; else throw "TODO: moved"; }
|
||||
|
||||
inline const T * operator->() const { return get_ptr(); }
|
||||
inline T * operator->() { return get_ptr(); }
|
||||
|
||||
inline const T & operator*() const { return get(); }
|
||||
inline T & operator*() { return get(); }
|
||||
|
||||
inline operator const T*() const { return get_ptr(); }
|
||||
inline operator T*() { return get_ptr(); }
|
||||
|
||||
inline aligned_ptr<T>& operator=(aligned_ptr<T>&& other)
|
||||
{
|
||||
if(ptr) aligned_ptr<void>::dealloc<T>(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)
|
||||
{
|
||||
return (*this = other.clone());
|
||||
}
|
||||
inline aligned_ptr(const aligned_ptr<T>& copy) : ptr(aligned_ptr<void>::make<T>(copy.get())){}
|
||||
T* const ptr;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
inline aligned_ptr<T> make_aligned(Args&&... init) { return aligned_ptr<T >(aligned_ptr_util::template make<T>(std::forward<Args>(init)...)); }
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#include <string>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <mem.h>
|
||||
|
||||
template<typename T>
|
||||
static inline T* not_null(T* ptr)
|
||||
{
|
||||
if(!ptr) throw "TODO: Nullptr except";
|
||||
return ptr;
|
||||
}
|
||||
|
||||
namespace mem
|
||||
{
|
||||
void* aligned_ptr<void >::_alloc(usize a, usize s) { return not_null<void>( aligned_alloc(a, s) ); }
|
||||
void aligned_ptr<void >::_dealloc(void* ptr) { free(ptr); }
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
auto ptr = mem::make_aligned<std::string>("hello");
|
||||
auto len = ptr->size();
|
||||
|
||||
printf("Stirng: %s, %lu\n", ptr->c_str(), (usize)len);
|
||||
}
|
Loading…
Reference in new issue