Add OwnedPtr and SharedPtr
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2022-12-23 10:23:13 +01:00
parent 9afaad8fed
commit bd4b05e534
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 165 additions and 0 deletions

View File

@ -0,0 +1,61 @@
#pragma once
#include <luna/Alloc.h>
#include <luna/Result.h>
template <typename T> class OwnedPtr
{
public:
OwnedPtr(T* ptr)
{
m_ptr = ptr;
}
~OwnedPtr()
{
if (m_ptr) delete m_ptr;
}
OwnedPtr(const OwnedPtr<T>& other) = delete;
OwnedPtr(OwnedPtr<T>&& other)
{
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
}
T* ptr() const
{
return m_ptr;
}
T* operator->() const
{
return m_ptr;
}
T& operator*() const
{
return *m_ptr;
}
private:
T* m_ptr;
};
template <typename T, class... Args> Result<OwnedPtr<T>> make_owned(Args... args)
{
T* raw = TRY(make<T>(args...));
return OwnedPtr<T> { raw };
}
template <typename T> OwnedPtr<T> adopt_owned(T* ptr)
{
return OwnedPtr<T> { ptr };
}
template <typename T> Result<OwnedPtr<T>> adopt_owned_if_nonnull(T* ptr)
{
if (ptr) return OwnedPtr<T> { ptr };
else
return err(ENOMEM);
}

View File

@ -0,0 +1,104 @@
#pragma once
#include <luna/Alloc.h>
#include <luna/Atomic.h>
#include <luna/DebugLog.h>
#include <luna/Result.h>
#include <luna/ScopeGuard.h>
namespace __detail
{
struct RefCount
{
void ref()
{
m_ref_count++;
}
bool unref()
{
m_ref_count--;
return m_ref_count == 0;
}
private:
Atomic<int> m_ref_count { 1 };
};
}
template <typename T> class SharedPtr
{
using RefCount = __detail::RefCount;
public:
SharedPtr(T* ptr, RefCount* ref_count) : m_ptr(ptr), m_ref_count(ref_count)
{
}
SharedPtr(const SharedPtr<T>& other) : m_ptr(other.m_ptr), m_ref_count(other.m_ref_count)
{
m_ref_count->ref();
}
SharedPtr(SharedPtr<T>&& other) : m_ptr(other.m_ptr), m_ref_count(other.m_ref_count)
{
other.m_ptr = nullptr;
other.m_ref_count = nullptr;
}
~SharedPtr()
{
if (m_ref_count && m_ref_count->unref())
{
delete m_ref_count;
delete m_ptr;
}
}
T* ptr() const
{
return m_ptr;
}
T* operator->() const
{
return m_ptr;
}
T& operator*() const
{
return *m_ptr;
}
private:
T* m_ptr;
RefCount* m_ref_count;
};
template <typename T, class... Args> Result<SharedPtr<T>> make_shared(Args... args)
{
using RefCount = __detail::RefCount;
RefCount* ref_count = TRY(make<RefCount>());
auto guard = make_scope_guard([&] { delete ref_count; });
T* ptr = TRY(make<T>(args...));
guard.deactivate();
return SharedPtr<T> { ptr, ref_count };
}
template <typename T> Result<SharedPtr<T>> adopt_shared(T* ptr)
{
using RefCount = __detail::RefCount;
RefCount* ref_count = TRY(make<RefCount>());
return SharedPtr<T> { ptr, ref_count };
}
template <typename T> Result<SharedPtr<T>> adopt_shared_if_nonnull(T* ptr)
{
if (ptr) return adopt_shared(ptr);
else
return err(ENOMEM);
}