#pragma once #include #include #include #include #include #include #include template class SharedPtr; template SharedPtr adopt_shared(T*); struct Shareable { void ref() { m_ref_count++; } bool unref() { m_ref_count--; return m_ref_count == 0; } Atomic m_ref_count { 1 }; }; template class SharedPtr { public: SharedPtr() { m_ptr = nullptr; } SharedPtr(T* ptr) : m_ptr(ptr) { } SharedPtr(const SharedPtr& other) : m_ptr(other.m_ptr) { if (m_ptr) shareable()->ref(); } SharedPtr(SharedPtr&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } template operator SharedPtr() { if (m_ptr) shareable()->ref(); return { (Tp*)m_ptr }; } ~SharedPtr() { if (m_ptr && shareable()->unref()) { delete m_ptr; } } SharedPtr& operator=(const SharedPtr& other) { if (&other == this) return *this; if (m_ptr && shareable()->unref()) { delete m_ptr; } m_ptr = other.m_ptr; if (m_ptr) shareable()->ref(); return *this; } bool operator==(const SharedPtr& other) { return m_ptr == other.m_ptr; } T* ptr() const { return m_ptr; } T* operator->() const { return m_ptr; } T& operator*() const { return *m_ptr; } operator bool() const { return m_ptr != nullptr; } private: T* m_ptr; Shareable* shareable() { static_assert(IsBaseOf); return (Shareable*)m_ptr; } }; template SharedPtr adopt_shared(T* ptr) { return SharedPtr { ptr }; } template Result> make_shared(Args... args) { T* raw_ptr = TRY(make(args...)); return adopt_shared(raw_ptr); } template Result> adopt_shared_if_nonnull(T* ptr) { if (ptr) return adopt_shared(ptr); else return err(ENOMEM); } template SharedPtr adopt_shared_from_owned(OwnedPtr&& other) { T* ptr = other.m_ptr; other.m_ptr = nullptr; return SharedPtr { ptr }; }