diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2018-06-22 13:09:01 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-22 13:09:01 -0400 |
| commit | d0c9571be3a2167a9f019310aca8f7cd326972c0 (patch) | |
| tree | 52aa2f14ec2c9d8d42bc6fcbd381ed9799c19533 /source/core/slang-com-ptr.h | |
| parent | e66d66b88e1c6ef8499708952fcbe3ba873f6e4c (diff) | |
Expose macros/functionality for defining interfaces (#604)
* Added Result definitions to the slang.h
* Removed slang-result.h and added slang-com-helper.h
* Move slang-com-ptr.h to be publically available.
* Add SLANG_IUNKNOWN macros to simplify implementing interfaces.
Use the SLANG_IUNKNOWN macros to in slang.c
* Removed slang-defines.h added outstanding defines to slang.h
Diffstat (limited to 'source/core/slang-com-ptr.h')
| -rw-r--r-- | source/core/slang-com-ptr.h | 206 |
1 files changed, 0 insertions, 206 deletions
diff --git a/source/core/slang-com-ptr.h b/source/core/slang-com-ptr.h deleted file mode 100644 index 765edbee5..000000000 --- a/source/core/slang-com-ptr.h +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef SLANG_COM_PTR_H -#define SLANG_COM_PTR_H - -#include "slang-defines.h" -#include "slang-result.h" - -#include <assert.h> - -namespace Slang { - -/*! \brief ComPtr is a simple smart pointer that manages types which implement COM based interfaces. -\details A class that implements a COM, must derive from the IUnknown interface or a type that matches -it's layout exactly (such as IForwardUnknown). Trying to use this template with a class that doesn't follow -these rules, will lead to undefined behavior. -This is a 'strong' pointer type, and will AddRef when a non null pointer is set and Release when the pointer -leaves scope. -Using 'detach' allows a pointer to be removed from the management of the ComPtr. -To set the smart pointer to null, there is the method setNull, or alternatively just assign SLANG_NULL/nullptr. - -One edge case using the template is that sometimes you want access as a pointer to a pointer. Sometimes this -is to write into the smart pointer, other times to pass as an array. To handle these different behaviors -there are the methods readRef and writeRef, which are used instead of the & (ref) operator. For example - -\code - -Void doSomething(ID3D12Resource** resources, IndexT numResources); - -// ... -ComPtr<ID3D12Resource> resources[3]; - -doSomething(resources[0].readRef(), SLANG_COUNT_OF(resource)); -\endcode - -A more common scenario writing to the pointer - -\code -IUnknown* unk = ...; - -ComPtr<ID3D12Resource> resource; -Result res = unk->QueryInterface(resource.writeRef()); -\endcode -*/ - -typedef SlangUUID Guid; - -SLANG_FORCE_INLINE bool operator==(const Guid& aIn, const Guid& bIn) -{ - // Use the largest type the honors the alignment of Guid - typedef uint32_t CmpType; - union GuidCompare - { - Guid guid; - CmpType data[sizeof(Guid) / sizeof(CmpType)]; - }; - // Type pun - so compiler can 'see' the pun and not break aliasing rules - const CmpType* a = reinterpret_cast<const GuidCompare&>(aIn).data; - const CmpType* b = reinterpret_cast<const GuidCompare&>(bIn).data; - // Make the guid comparison a single branch, by not using short circuit - return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0; -} - -SLANG_FORCE_INLINE bool operator!=(const Guid& a, const Guid& b) -{ - return !(a == b); -} - -// Allows for defining of a GUID that works in C++ and C which defines in a format similar to microsofts INTERFACE style -// MIDL_INTERFACE("00000000-0000-0000-C000-00 00 00 00 00 46") - -#define SLANG_GUID_BYTE(x, index) ((uint8_t)(SLANG_UINT64(0x##x) >> (8 * index))) - -#define SLANG_MAKE_GUID(data0, data1, data2, shortTail, tail) \ - { (uint32_t)(0x##data0), (uint16_t)(0x##data1), (uint16_t)(0x##data2), \ - { (uint8_t)(0x##shortTail >> 8), (uint8_t)(0x##shortTail & 0xff), \ - SLANG_GUID_BYTE(tail,5), SLANG_GUID_BYTE(tail,4), SLANG_GUID_BYTE(tail,3), SLANG_GUID_BYTE(tail,2), SLANG_GUID_BYTE(tail,1), SLANG_GUID_BYTE(tail,0) \ - }} - -// Compatible with Microsoft IUnknown -static const Guid IID_IComUnknown = SLANG_MAKE_GUID(00000000, 0000, 0000, C000, 000000000046); - -typedef ISlangUnknown IComUnknown; - -// Enum to force initializing as an attach (without adding a reference) -enum InitAttach -{ - INIT_ATTACH -}; - -template <class T> -class ComPtr -{ -public: - typedef T Type; - typedef ComPtr ThisType; - typedef IComUnknown* Ptr; - - /// Constructors - /// Default Ctor. Sets to nullptr - SLANG_FORCE_INLINE ComPtr() :m_ptr(nullptr) {} - /// Sets, and ref counts. - SLANG_FORCE_INLINE explicit ComPtr(T* ptr) :m_ptr(ptr) { if (ptr) ((Ptr)ptr)->addRef(); } - /// The copy ctor - SLANG_FORCE_INLINE ComPtr(const ThisType& rhs) : m_ptr(rhs.m_ptr) { if (m_ptr) ((Ptr)m_ptr)->addRef(); } - - /// Ctor without adding to ref count. - SLANG_FORCE_INLINE explicit ComPtr(InitAttach, T* ptr) :m_ptr(ptr) { } - /// Ctor without adding to ref count - SLANG_FORCE_INLINE ComPtr(InitAttach, const ThisType& rhs) : m_ptr(rhs.m_ptr) { } - -#ifdef SLANG_HAS_MOVE_SEMANTICS - /// Move Ctor - SLANG_FORCE_INLINE ComPtr(ThisType&& rhs) : m_ptr(rhs.m_ptr) { rhs.m_ptr = nullptr; } - /// Move assign - SLANG_FORCE_INLINE ComPtr& operator=(ThisType&& rhs) { T* swap = m_ptr; m_ptr = rhs.m_ptr; rhs.m_ptr = swap; return *this; } -#endif - - /// Destructor releases the pointer, assuming it is set - SLANG_FORCE_INLINE ~ComPtr() { if (m_ptr) ((Ptr)m_ptr)->release(); } - - // !!! Operators !!! - - /// Returns the dumb pointer - SLANG_FORCE_INLINE operator T *() const { return m_ptr; } - - SLANG_FORCE_INLINE T& operator*() { return *m_ptr; } - /// For making method invocations through the smart pointer work through the dumb pointer - SLANG_FORCE_INLINE T* operator->() const { return m_ptr; } - - /// Assign - SLANG_FORCE_INLINE const ThisType &operator=(const ThisType& rhs); - /// Assign from dumb ptr - SLANG_FORCE_INLINE T* operator=(T* in); - - /// Get the pointer and don't ref - SLANG_FORCE_INLINE T* get() const { return m_ptr; } - /// Release a contained nullptr pointer if set - SLANG_FORCE_INLINE void setNull(); - - /// Detach - SLANG_FORCE_INLINE T* detach() { T* ptr = m_ptr; m_ptr = nullptr; return ptr; } - /// Set to a pointer without changing the ref count - SLANG_FORCE_INLINE void attach(T* in) { m_ptr = in; } - - /// Get ready for writing (nulls contents) - SLANG_FORCE_INLINE T** writeRef() { setNull(); return &m_ptr; } - /// Get for read access - SLANG_FORCE_INLINE T*const* readRef() const { return &m_ptr; } - - /// Swap - void swap(ThisType& rhs); - -protected: - /// Gets the address of the dumb pointer. - // Disabled: use writeRef and readRef to get a reference based on usage. - SLANG_FORCE_INLINE T** operator&(); - - T* m_ptr; -}; - -//---------------------------------------------------------------------------- -template <typename T> -void ComPtr<T>::setNull() -{ - if (m_ptr) - { - ((Ptr)m_ptr)->release(); - m_ptr = nullptr; - } -} -//---------------------------------------------------------------------------- -/* template <typename T> -T** ComPtr<T>::operator&() -{ - assert(m_ptr == nullptr); - return &m_ptr; -} */ -//---------------------------------------------------------------------------- -template <typename T> -const ComPtr<T>& ComPtr<T>::operator=(const ThisType& rhs) -{ - if (rhs.m_ptr) ((Ptr)rhs.m_ptr)->addRef(); - if (m_ptr) ((Ptr)m_ptr)->release(); - m_ptr = rhs.m_ptr; - return *this; -} -//---------------------------------------------------------------------------- -template <typename T> -T* ComPtr<T>::operator=(T* ptr) -{ - if (ptr) ((Ptr)ptr)->addRef(); - if (m_ptr) ((Ptr)m_ptr)->release(); - m_ptr = ptr; - return m_ptr; -} -//---------------------------------------------------------------------------- -template <typename T> -void ComPtr<T>::swap(ThisType& rhs) -{ - T* tmp = m_ptr; - m_ptr = rhs.m_ptr; - rhs.m_ptr = tmp; -} - -} // namespace Slang - -#endif // SLANG_COM_PTR_H |
