2022-12-23 09:23:13 +00:00
|
|
|
#pragma once
|
|
|
|
#include <luna/Alloc.h>
|
|
|
|
#include <luna/Atomic.h>
|
2023-06-20 19:39:41 +00:00
|
|
|
#include <luna/Hash.h>
|
2022-12-31 11:02:15 +00:00
|
|
|
#include <luna/OwnedPtr.h>
|
2022-12-23 09:23:13 +00:00
|
|
|
#include <luna/Result.h>
|
|
|
|
#include <luna/ScopeGuard.h>
|
2023-07-30 09:32:46 +00:00
|
|
|
#include <luna/TypeTraits.h>
|
2022-12-23 09:23:13 +00:00
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
template <typename T> class SharedPtr;
|
|
|
|
template <typename T> SharedPtr<T> adopt_shared(T*);
|
|
|
|
|
|
|
|
struct Shareable
|
2022-12-23 09:23:13 +00:00
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
void ref()
|
2022-12-23 09:23:13 +00:00
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
m_ref_count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool unref()
|
|
|
|
{
|
|
|
|
m_ref_count--;
|
|
|
|
return m_ref_count == 0;
|
|
|
|
}
|
|
|
|
|
2023-08-03 08:32:22 +00:00
|
|
|
Atomic<int> m_ref_count { 0 };
|
2023-07-30 09:32:46 +00:00
|
|
|
};
|
2022-12-23 09:23:13 +00:00
|
|
|
|
|
|
|
template <typename T> class SharedPtr
|
|
|
|
{
|
|
|
|
public:
|
2023-01-13 17:54:39 +00:00
|
|
|
SharedPtr()
|
|
|
|
{
|
|
|
|
m_ptr = nullptr;
|
|
|
|
}
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
SharedPtr(T* ptr) : m_ptr(ptr)
|
2022-12-23 09:23:13 +00:00
|
|
|
{
|
2023-08-03 08:32:22 +00:00
|
|
|
if (m_ptr) shareable()->ref();
|
2022-12-23 09:23:13 +00:00
|
|
|
}
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
SharedPtr(const SharedPtr<T>& other) : m_ptr(other.m_ptr)
|
2022-12-23 09:23:13 +00:00
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
if (m_ptr) shareable()->ref();
|
2022-12-23 09:23:13 +00:00
|
|
|
}
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
SharedPtr(SharedPtr<T>&& other) : m_ptr(other.m_ptr)
|
2022-12-23 09:23:13 +00:00
|
|
|
{
|
|
|
|
other.m_ptr = nullptr;
|
|
|
|
}
|
|
|
|
|
2023-01-31 18:59:06 +00:00
|
|
|
template <typename Tp> operator SharedPtr<Tp>()
|
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
return { (Tp*)m_ptr };
|
2023-01-31 18:59:06 +00:00
|
|
|
}
|
|
|
|
|
2022-12-23 09:23:13 +00:00
|
|
|
~SharedPtr()
|
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
if (m_ptr && shareable()->unref()) { delete m_ptr; }
|
2022-12-23 09:23:13 +00:00
|
|
|
}
|
|
|
|
|
2022-12-23 09:31:48 +00:00
|
|
|
SharedPtr<T>& operator=(const SharedPtr<T>& other)
|
|
|
|
{
|
|
|
|
if (&other == this) return *this;
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
if (m_ptr && shareable()->unref()) { delete m_ptr; }
|
2022-12-23 09:31:48 +00:00
|
|
|
|
|
|
|
m_ptr = other.m_ptr;
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
if (m_ptr) shareable()->ref();
|
2022-12-23 09:31:48 +00:00
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2023-06-20 19:39:41 +00:00
|
|
|
bool operator==(const SharedPtr<T>& other)
|
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
return m_ptr == other.m_ptr;
|
2023-06-20 19:39:41 +00:00
|
|
|
}
|
|
|
|
|
2022-12-23 09:23:13 +00:00
|
|
|
T* ptr() const
|
|
|
|
{
|
|
|
|
return m_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
T* operator->() const
|
|
|
|
{
|
|
|
|
return m_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
T& operator*() const
|
|
|
|
{
|
|
|
|
return *m_ptr;
|
|
|
|
}
|
|
|
|
|
2023-02-25 16:09:03 +00:00
|
|
|
operator bool() const
|
|
|
|
{
|
|
|
|
return m_ptr != nullptr;
|
|
|
|
}
|
|
|
|
|
2022-12-23 09:23:13 +00:00
|
|
|
private:
|
|
|
|
T* m_ptr;
|
2023-07-30 09:32:46 +00:00
|
|
|
|
|
|
|
Shareable* shareable()
|
|
|
|
{
|
|
|
|
static_assert(IsBaseOf<Shareable, T>);
|
|
|
|
return (Shareable*)m_ptr;
|
|
|
|
}
|
2022-12-23 09:23:13 +00:00
|
|
|
};
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
template <typename T> SharedPtr<T> adopt_shared(T* ptr)
|
2022-12-23 09:23:13 +00:00
|
|
|
{
|
2023-07-30 09:32:46 +00:00
|
|
|
return SharedPtr<T> { ptr };
|
2022-12-23 09:23:13 +00:00
|
|
|
}
|
|
|
|
|
2023-02-14 18:59:44 +00:00
|
|
|
template <typename T, class... Args> Result<SharedPtr<T>> make_shared(Args... args)
|
|
|
|
{
|
|
|
|
T* raw_ptr = TRY(make<T>(args...));
|
|
|
|
return adopt_shared(raw_ptr);
|
|
|
|
}
|
|
|
|
|
2022-12-23 09:23:13 +00:00
|
|
|
template <typename T> Result<SharedPtr<T>> adopt_shared_if_nonnull(T* ptr)
|
|
|
|
{
|
|
|
|
if (ptr) return adopt_shared(ptr);
|
|
|
|
else
|
|
|
|
return err(ENOMEM);
|
2022-12-31 11:02:15 +00:00
|
|
|
}
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
template <typename T> SharedPtr<T> adopt_shared_from_owned(OwnedPtr<T>&& other)
|
2022-12-31 11:02:15 +00:00
|
|
|
{
|
|
|
|
T* ptr = other.m_ptr;
|
|
|
|
other.m_ptr = nullptr;
|
|
|
|
|
2023-07-30 09:32:46 +00:00
|
|
|
return SharedPtr<T> { ptr };
|
2023-01-02 12:07:29 +00:00
|
|
|
}
|