// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "HAL/Platform.h" // HEADER_UNIT_SKIP - Included through RefCounted namespace mu { //! \brief Intrusive smart pointer similar to the one in the boost libraries (intrusive_ptr<>) //! //! Some of the objects used by the runtime use reference counting to control their life-cycle. //! When an objects is returned in such a pointer, the user should keep this pointer valid while //! the data is in use, and clear it when done by assigning nullptr to it. The data returned //! in Ptr pointers should never be directly deleted. //! //! The underlying lower-level pointer can be obtained with the get() method, but it should //! never be stored, since it will be valid only while there are valid Ptr<> to the same object. //! //! \ingroup runtime template class Ptr { public: Ptr( T* p = nullptr, bool add_ref = true ) { m_ptr = p; if( m_ptr != nullptr && add_ref ) { mutable_ptr_add_ref( m_ptr ); } } template Ptr( Ptr const& rhs ) : m_ptr( rhs.get() ) { if( m_ptr != nullptr ) { mutable_ptr_add_ref( m_ptr ); } } //! Assign constructor Ptr( Ptr const& rhs ) : m_ptr( rhs.m_ptr ) { if( m_ptr != nullptr ) { mutable_ptr_add_ref( m_ptr ); } } //! Move constructor Ptr( Ptr&& rhs ) { m_ptr = rhs.m_ptr; rhs.m_ptr = nullptr; } ~Ptr() { if( m_ptr != nullptr ) { mutable_ptr_release( m_ptr ); } } template Ptr& operator=( Ptr const& rhs ) { Ptr(rhs).swap(*this); return *this; } //! Assign with copy Ptr& operator=( Ptr const& rhs) { Ptr(rhs).swap(*this); return *this; } //! Assign with move Ptr& operator=( Ptr&& rhs) { if( m_ptr != nullptr ) { mutable_ptr_release( m_ptr ); } m_ptr = rhs.m_ptr; rhs.m_ptr = nullptr; return *this; } Ptr& operator=( T* rhs) { Ptr(rhs).swap(*this); return *this; } void reset() { Ptr().swap( *this ); } void reset( T* rhs ) { Ptr( rhs ).swap( *this ); } T* get() const { return m_ptr; } T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } FORCEINLINE explicit operator bool() const { return m_ptr != nullptr; } void swap( Ptr& rhs) { T * tmp = m_ptr; m_ptr = rhs.m_ptr; rhs.m_ptr = tmp; } private: T* m_ptr = nullptr; }; template inline bool operator==( Ptr const& a, Ptr const& b ) { return a.get() == b.get(); } template inline bool operator!=( Ptr const& a, Ptr const& b ) { return a.get() != b.get(); } template inline bool operator==( Ptr const& a, U* b ) { return a.get() == b; } template inline bool operator!=( Ptr const& a, U* b ) { return a.get() != b; } template inline bool operator==( T* a, Ptr const& b ) { return a == b.get(); } template inline bool operator!=( T* a, Ptr const& b ) { return a != b.get(); } template inline bool operator<( Ptr const& a, Ptr const& b ) { return ( a.get() < b.get() ); } template void swap( Ptr& lhs, Ptr& rhs ) { lhs.swap(rhs); } template Ptr static_pointer_cast( Ptr const & p) { return static_cast(p.get()); } template Ptr const_pointer_cast( Ptr const & p) { return const_cast(p.get()); } }