summaryrefslogtreecommitdiff
path: root/include/slang-com-ptr.h
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2024-10-29 14:49:26 +0800
committerGitHub <noreply@github.com>2024-10-29 14:49:26 +0800
commitf65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch)
treeea1d61342cd29368e19135000ec2948813096205 /include/slang-com-ptr.h
parenta729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff)
format
* format * Minor test fixes * enable checking cpp format in ci
Diffstat (limited to 'include/slang-com-ptr.h')
-rw-r--r--include/slang-com-ptr.h232
1 files changed, 141 insertions, 91 deletions
diff --git a/include/slang-com-ptr.h b/include/slang-com-ptr.h
index 00cc9dbb1..e9d211d92 100644
--- a/include/slang-com-ptr.h
+++ b/include/slang-com-ptr.h
@@ -6,20 +6,21 @@
#include <assert.h>
#include <cstddef>
-namespace Slang {
+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 ISlangUnknown). 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
+\details A class that implements a COM, must derive from the IUnknown interface or a type that
+matches it's layout exactly (such as ISlangUnknown). 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);
@@ -44,115 +45,164 @@ enum InitAttach
INIT_ATTACH
};
-template <class T>
+template<class T>
class ComPtr
{
public:
- typedef T Type;
- typedef ComPtr ThisType;
- typedef ISlangUnknown* Ptr;
-
- /// Constructors
- /// Default Ctor. Sets to nullptr
- SLANG_FORCE_INLINE ComPtr() :m_ptr(nullptr) {}
- SLANG_FORCE_INLINE ComPtr(std::nullptr_t) : 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) { }
+ typedef T Type;
+ typedef ComPtr ThisType;
+ typedef ISlangUnknown* Ptr;
+
+ /// Constructors
+ /// Default Ctor. Sets to nullptr
+ SLANG_FORCE_INLINE ComPtr()
+ : m_ptr(nullptr)
+ {
+ }
+ SLANG_FORCE_INLINE ComPtr(std::nullptr_t)
+ : 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; }
+ /// 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);
+ /// 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.
+ /// Gets the address of the dumb pointer.
// Disabled: use writeRef and readRef to get a reference based on usage.
#ifndef SLANG_COM_PTR_ENABLE_REF_OPERATOR
- SLANG_FORCE_INLINE T** operator&() = delete;
+ SLANG_FORCE_INLINE T** operator&() = delete;
#endif
- T* m_ptr;
+ T* m_ptr;
};
//----------------------------------------------------------------------------
-template <typename T>
+template<typename T>
void ComPtr<T>::setNull()
{
- if (m_ptr)
- {
- ((Ptr)m_ptr)->release();
- m_ptr = nullptr;
- }
+ if (m_ptr)
+ {
+ ((Ptr)m_ptr)->release();
+ m_ptr = nullptr;
+ }
}
//----------------------------------------------------------------------------
-template <typename T>
+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;
+ 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>
+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;
+ if (ptr)
+ ((Ptr)ptr)->addRef();
+ if (m_ptr)
+ ((Ptr)m_ptr)->release();
+ m_ptr = ptr;
+ return m_ptr;
}
//----------------------------------------------------------------------------
-template <typename T>
+template<typename T>
void ComPtr<T>::swap(ThisType& rhs)
{
- T* tmp = m_ptr;
- m_ptr = rhs.m_ptr;
- rhs.m_ptr = tmp;
+ T* tmp = m_ptr;
+ m_ptr = rhs.m_ptr;
+ rhs.m_ptr = tmp;
}
} // namespace Slang