BAN: Add RefCounted<> and Unique<>

We have now maybe functional smart pointers
This commit is contained in:
Bananymous 2023-01-30 18:54:37 +02:00
parent 1687028ed5
commit f10a57dcec
2 changed files with 133 additions and 3 deletions

View File

@ -1,11 +1,18 @@
#pragma once #pragma once
#include <BAN/Errors.h>
#include <BAN/Move.h>
#include <BAN/NoCopyMove.h>
#if defined(__is_kernel) #if defined(__is_kernel)
#include <kernel/kmalloc.h> #include <kernel/kmalloc.h>
#else #else
#include <stdlib.h> #include <stdlib.h>
#endif #endif
#include <stdint.h>
namespace BAN namespace BAN
{ {
#if defined(__is_kernel) #if defined(__is_kernel)
@ -18,24 +25,136 @@ namespace BAN
#endif #endif
template<typename T> template<typename T>
class OwnPtr class Unique
{ {
BAN_NON_COPYABLE(Unique<T>);
public: public:
template<typename... Args> template<typename... Args>
OwnPtr(const Args&... args) Unique(const Args&... args)
{ {
m_pointer = new T(args...); m_pointer = new T(args...);
} }
~OwnPtr() ~Unique()
{ {
delete m_pointer; delete m_pointer;
} }
operator bool() const
{
return m_pointer;
}
private: private:
T* m_pointer = nullptr; T* m_pointer = nullptr;
}; };
template<typename T>
class RefCounted
{
public:
RefCounted() { }
RefCounted(T* pointer)
{
if (pointer)
{
m_pointer = pointer;
m_count = new int32_t(1);
ASSERT(m_count);
}
}
RefCounted(const RefCounted<T>& other)
{
*this = other;
}
RefCounted(RefCounted<T>&& other)
{
*this = Move(other);
}
~RefCounted()
{
Reset();
}
template<typename... Args>
static RefCounted<T> Create(Args... args)
{
return RefCounted<T>(new T(Forward<Args>(args)...), new int32_t(1));
}
RefCounted<T>& operator=(const RefCounted<T>& other)
{
Reset();
if (other)
{
m_pointer = other.m_pointer;
m_count = other.m_count;
(*m_count)++;
}
return *this;
}
RefCounted<T>& operator=(RefCounted<T>&& 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<T>& 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; } inline void* operator new(size_t, void* addr) { return addr; }

View File

@ -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