diff --git a/BAN/include/BAN/Memory.h b/BAN/include/BAN/Memory.h index 155b1125b..3c6657186 100644 --- a/BAN/include/BAN/Memory.h +++ b/BAN/include/BAN/Memory.h @@ -1,11 +1,18 @@ #pragma once + +#include +#include +#include + #if defined(__is_kernel) #include #else #include #endif +#include + namespace BAN { #if defined(__is_kernel) @@ -18,24 +25,136 @@ namespace BAN #endif template - class OwnPtr + class Unique { + BAN_NON_COPYABLE(Unique); + public: template - OwnPtr(const Args&... args) + Unique(const Args&... args) { m_pointer = new T(args...); } - ~OwnPtr() + ~Unique() { delete m_pointer; } + operator bool() const + { + return m_pointer; + } + private: T* m_pointer = nullptr; }; + template + class RefCounted + { + public: + RefCounted() { } + RefCounted(T* pointer) + { + if (pointer) + { + m_pointer = pointer; + m_count = new int32_t(1); + ASSERT(m_count); + } + } + RefCounted(const RefCounted& other) + { + *this = other; + } + RefCounted(RefCounted&& other) + { + *this = Move(other); + } + ~RefCounted() + { + Reset(); + } + + template + static RefCounted Create(Args... args) + { + return RefCounted(new T(Forward(args)...), new int32_t(1)); + } + + RefCounted& operator=(const RefCounted& other) + { + Reset(); + if (other) + { + m_pointer = other.m_pointer; + m_count = other.m_count; + (*m_count)++; + } + return *this; + } + + RefCounted& operator=(RefCounted&& other) + { + Reset(); + m_pointer = other.m_pointer; + m_count = other.m_count; + other.m_pointer = nullptr; + other.m_count = nullptr; + if (!(*this)) + Reset(); + return *this; + } + + T& operator*() { return *m_pointer;} + const T& operator*() const { return *m_pointer;} + + T* operator->() { return m_pointer; } + const T* operator->() const { return m_pointer; } + + void Reset() + { + ASSERT(!m_count == !m_pointer); + if (!m_count) + return; + (*m_count)--; + if (*m_count == 0) + { + delete m_count; + delete m_pointer; + } + m_count = nullptr; + m_pointer = nullptr; + } + + operator bool() const + { + ASSERT(!m_count == !m_pointer); + return m_count && *m_count > 0; + } + + bool operator==(const RefCounted& other) const + { + if (m_pointer != other.m_pointer) + return false; + ASSERT(m_count == other.m_count); + return !m_count || *m_count > 0; + } + + private: + RefCounted(T* pointer, int32_t* count) + : m_pointer(pointer) + , m_count(count) + { + ASSERT(!pointer == !count); + } + + private: + T* m_pointer = nullptr; + int32_t* m_count = nullptr; + }; + } inline void* operator new(size_t, void* addr) { return addr; } diff --git a/BAN/include/BAN/NoCopyMove.h b/BAN/include/BAN/NoCopyMove.h new file mode 100644 index 000000000..a60c56ee2 --- /dev/null +++ b/BAN/include/BAN/NoCopyMove.h @@ -0,0 +1,11 @@ +#pragma once + +#define BAN_NON_COPYABLE(class) \ + private: \ + class(const class&) = delete; \ + class& operator=(const class&) = delete + +#define BAN_NON_MOVABLE(class) \ + private: \ + class(class&&) = delete; \ + class& operator=(class&&) = delete