#pragma once #include namespace BAN { template class Weakable; template class WeakPtr; template class WeakLink : public RefCounted> { public: RefPtr lock() { ASSERT(m_ptr); return raw_ptr(); } T* raw_ptr() { return m_ptr; } bool valid() const { return m_ptr; } void invalidate() { m_ptr = nullptr; } private: WeakLink(T* ptr) : m_ptr(ptr) {} private: T* m_ptr; friend class RefPtr>; }; template class Weakable { public: ~Weakable() { if (m_link) m_link->invalidate(); } ErrorOr> get_weak_ptr() const { if (!m_link) m_link = TRY(RefPtr>::create((T*)this)); return WeakPtr(m_link); } private: mutable RefPtr> m_link; }; template class WeakPtr { public: WeakPtr() = default; WeakPtr(WeakPtr&& other) { *this = move(other); } WeakPtr(const WeakPtr& other) { *this = other; } WeakPtr(const RefPtr& other) { *this = other; } WeakPtr& operator=(WeakPtr&& other) { clear(); m_link = move(other.m_link); return *this; } WeakPtr& operator=(const WeakPtr& other) { clear(); m_link = other.m_link; return *this; } WeakPtr& operator=(const RefPtr& other) { clear(); if (other) m_link = MUST(other->get_weak_ptr()).move_link(); return *this; } RefPtr lock() { if (m_link->valid()) return m_link->lock(); return nullptr; } void clear() { m_link.clear(); } bool valid() const { return m_link && m_link->valid(); } private: WeakPtr(const RefPtr>& link) : m_link(link) { } RefPtr>&& move_link() { return move(m_link); } private: RefPtr> m_link; friend class Weakable; }; }