BAN: Implement basic WeakPtr
This can be constructed from classes that inherit from Weakable
This commit is contained in:
		
							parent
							
								
									8caba1e774
								
							
						
					
					
						commit
						b62186441b
					
				|  | @ -0,0 +1,107 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <BAN/RefPtr.h> | ||||
| 
 | ||||
| namespace BAN | ||||
| { | ||||
| 
 | ||||
| 	template<typename T> | ||||
| 	class Weakable; | ||||
| 
 | ||||
| 	template<typename T> | ||||
| 	class WeakPtr; | ||||
| 
 | ||||
| 	template<typename T> | ||||
| 	class WeakLink : public RefCounted<WeakLink<T>> | ||||
| 	{ | ||||
| 	public: | ||||
| 		RefPtr<T> 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<WeakLink<T>>; | ||||
| 	}; | ||||
| 
 | ||||
| 	template<typename T> | ||||
| 	class Weakable | ||||
| 	{ | ||||
| 	public: | ||||
| 		~Weakable() | ||||
| 		{ | ||||
| 			if (m_link) | ||||
| 				m_link->invalidate(); | ||||
| 		} | ||||
| 
 | ||||
| 		ErrorOr<WeakPtr<T>> get_weak_ptr() const | ||||
| 		{ | ||||
| 			if (!m_link) | ||||
| 				m_link = TRY(RefPtr<WeakLink<T>>::create((T*)this)); | ||||
| 			return WeakPtr<T>(m_link); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		mutable RefPtr<WeakLink<T>> m_link; | ||||
| 	}; | ||||
| 
 | ||||
| 	template<typename T> | ||||
| 	class WeakPtr | ||||
| 	{ | ||||
| 	public: | ||||
| 		WeakPtr() = default; | ||||
| 		WeakPtr(WeakPtr&& other)		{ *this = move(other); } | ||||
| 		WeakPtr(const WeakPtr& other)	{ *this = other; } | ||||
| 		WeakPtr(const RefPtr<T>& 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<T>& other) | ||||
| 		{ | ||||
| 			clear(); | ||||
| 			if (other) | ||||
| 				m_link = MUST(other->get_weak_ptr()).move_link(); | ||||
| 			return *this; | ||||
| 		} | ||||
| 
 | ||||
| 		RefPtr<T> 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<WeakLink<T>>& link) | ||||
| 			: m_link(link) | ||||
| 		{ } | ||||
| 
 | ||||
| 		RefPtr<WeakLink<T>>&& move_link() { return move(m_link); } | ||||
| 
 | ||||
| 	private: | ||||
| 		RefPtr<WeakLink<T>> m_link; | ||||
| 
 | ||||
| 		friend class Weakable<T>; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue