yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#ifndef SLANG_COM_PTR_H 2#define SLANG_COM_PTR_H 3 4#include "slang-com-helper.h" 5 6#include <assert.h> 7#include <cstddef> 8 9namespace Slang 10{ 11 12/*! \brief ComPtr is a simple smart pointer that manages types which implement COM based interfaces. 13\details A class that implements a COM, must derive from the IUnknown interface or a type that 14matches it's layout exactly (such as ISlangUnknown). Trying to use this template with a class that 15doesn't follow these rules, will lead to undefined behavior. This is a 'strong' pointer type, and 16will AddRef when a non null pointer is set and Release when the pointer leaves scope. Using 'detach' 17allows a pointer to be removed from the management of the ComPtr. To set the smart pointer to null, 18there is the method setNull, or alternatively just assign SLANG_NULL/nullptr. 19 20One edge case using the template is that sometimes you want access as a pointer to a pointer. 21Sometimes this is to write into the smart pointer, other times to pass as an array. To handle these 22different behaviors there are the methods readRef and writeRef, which are used instead of the & 23(ref) operator. For example 24 25\code 26Void doSomething(ID3D12Resource** resources, IndexT numResources); 27// ... 28ComPtr<ID3D12Resource> resources[3]; 29doSomething(resources[0].readRef(), SLANG_COUNT_OF(resource)); 30\endcode 31 32A more common scenario writing to the pointer 33 34\code 35IUnknown* unk = ...; 36 37ComPtr<ID3D12Resource> resource; 38Result res = unk->QueryInterface(resource.writeRef()); 39\endcode 40*/ 41 42// Enum to force initializing as an attach (without adding a reference) 43enum InitAttach 44{ 45INIT_ATTACH 46}; 47 48template < class T > 49class ComPtr 50{ 51public : 52typedef T Type ; 53typedef ComPtr ThisType ; 54typedef ISlangUnknown * Ptr ; 55 56/// Constructors 57/// Default Ctor. Sets to nullptr 58SLANG_FORCE_INLINE ComPtr () 59 :m_ptr (nullptr ) 60 { 61 } 62SLANG_FORCE_INLINE ComPtr (std ::nullptr_t ) 63 :m_ptr (nullptr ) 64 { 65 } 66/// Sets, and ref counts. 67SLANG_FORCE_INLINE explicit ComPtr (T * ptr ) 68 :m_ptr (ptr ) 69 { 70if (ptr ) 71 ((Ptr )ptr )-> addRef (); 72 } 73/// The copy ctor 74SLANG_FORCE_INLINE ComPtr (const ThisType & rhs ) 75 :m_ptr (rhs .m_ptr ) 76 { 77if (m_ptr ) 78 ((Ptr )m_ptr )-> addRef (); 79 } 80 81/// Ctor without adding to ref count. 82SLANG_FORCE_INLINE explicit ComPtr (InitAttach ,T * ptr ) 83 :m_ptr (ptr ) 84 { 85 } 86/// Ctor without adding to ref count 87SLANG_FORCE_INLINE ComPtr (InitAttach ,const ThisType & rhs ) 88 :m_ptr (rhs .m_ptr ) 89 { 90 } 91 92#ifdef SLANG_HAS_MOVE_SEMANTICS 93/// Move Ctor 94SLANG_FORCE_INLINE ComPtr (ThisType && rhs ) 95 :m_ptr (rhs .m_ptr ) 96 { 97rhs .m_ptr = nullptr ; 98 } 99/// Move assign 100SLANG_FORCE_INLINE ComPtr & operator = (ThisType && rhs ) 101 { 102T * swap = m_ptr ; 103m_ptr = rhs .m_ptr ; 104rhs .m_ptr = swap ; 105return * this ; 106 } 107#endif 108 109/// Destructor releases the pointer, assuming it is set 110SLANG_FORCE_INLINE ~ComPtr () 111 { 112if (m_ptr ) 113 ((Ptr )m_ptr )-> release (); 114 } 115 116// !!! Operators !!! 117 118/// Returns the dumb pointer 119SLANG_FORCE_INLINE operator T * ()const {return m_ptr ; } 120 121SLANG_FORCE_INLINE T & operator * () {return * m_ptr ; } 122/// For making method invocations through the smart pointer work through the dumb pointer 123SLANG_FORCE_INLINE T * operator -> () const { return m_ptr ; } 124 125/// Assign 126SLANG_FORCE_INLINE const ThisType & operator = ( const ThisType & rhs ); 127/// Assign from dumb ptr 128SLANG_FORCE_INLINE T * operator = ( T * in ); 129 130/// Get the pointer and don't ref 131SLANG_FORCE_INLINE T * get() const { return m_ptr ; } 132/// Release a contained nullptr pointer if set 133SLANG_FORCE_INLINE void setNull (); 134 135/// Detach 136SLANG_FORCE_INLINE T * detach() 137{ 138T * ptr = m_ptr ; 139m_ptr = nullptr ; 140return ptr ; 141} 142/// Set to a pointer without changing the ref count 143SLANG_FORCE_INLINE void attach ( T * in ) { m_ptr = in ; } 144 145/// Get ready for writing (nulls contents) 146SLANG_FORCE_INLINE T ** writeRef() 147{ 148setNull(); 149return & m_ptr ; 150} 151/// Get for read access 152SLANG_FORCE_INLINE T * const * readRef() const { return & m_ptr ; } 153 154/// Swap 155void swap( ThisType & rhs ); 156 157protected : 158/// Gets the address of the dumb pointer. 159// Disabled: use writeRef and readRef to get a reference based on usage. 160#ifndef SLANG_COM_PTR_ENABLE_REF_OPERATOR 161SLANG_FORCE_INLINE T ** operator & ( ) = delete; 162#endif 163 164T * m_ptr; 165}; 166 167//---------------------------------------------------------------------------- 168template < typename T > 169void ComPtr < T > :: setNull () 170{ 171if (m_ptr) 172{ 173(( Ptr )m_ptr) -> release (); 174m_ptr = nullptr ; 175} 176} 177//---------------------------------------------------------------------------- 178template < typename T > 179const ComPtr < T >& ComPtr < T > ::operator = ( const ThisType & rhs) 180{ 181if (rhs. m_ptr ) 182(( Ptr )rhs. m_ptr ) -> addRef (); 183if (m_ptr) 184(( Ptr )m_ptr) -> release (); 185m_ptr = rhs. m_ptr ; 186return * this; 187} 188//---------------------------------------------------------------------------- 189template < typename T > 190T * ComPtr < T > ::operator = ( T * ptr) 191{ 192if (ptr) 193(( Ptr )ptr) -> addRef (); 194if (m_ptr) 195(( Ptr )m_ptr) -> release (); 196m_ptr = ptr; 197return m_ptr; 198} 199//---------------------------------------------------------------------------- 200template < typename T > 201void ComPtr < T > :: swap (ThisType & rhs) 202{ 203T * tmp = m_ptr; 204m_ptr = rhs. m_ptr ; 205rhs. m_ptr = tmp; 206} 207 208} // namespace Slang 209 210#endif // SLANG_COM_PTR_H