diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2024-07-17 12:53:19 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-17 10:53:19 -0700 |
| commit | 2db15080085856ed9b5f20642dbb354aac59a888 (patch) | |
| tree | 4f6558b8c3aac5e5191edaa092230ecb449f4a44 /include/slang-com-ptr.h | |
| parent | 7d07bd29fee7dcd74fe73940723effc68f427e67 (diff) | |
Move the file public header files to `include` dir (#4636)
* Move the file public header files to `include` dir
Close the issue (#4635).
Move the following headers files to a `include` dir
located at root dir of slang repo:
slang-com-helper.h -> include/slang-com-helper.h
slang-com-ptr.h -> include/slang-com-ptr.h
slang-gfx.h -> include/slang-gfx.h
slang.h -> include/slang.h
Change cmake/SlangTarget.cmake to add include path to
every target, and change the source file to use
"#include <slang.h>" to include the public headers.
The source code update is by the script like follow:
```
fileNames_slang=$(grep -r "\".*slang\.h\"" source/ -l)
for fileName in "${fileNames_slang[@]}"
do
echo "$fileName"
sed -i "s/\".*slang\.h\"/\"slang\.h\"/" $fileName
done
```
* Fix the test issues
* Fix cpu test issues by adding include seach path
* Update cmake to not add include path for every target
Also change "#include <slang.h>" to "include "slang.h" " to
make the coding style consistent with other slang code.
* Change public include to private include for unit-test and slang-glslang
Diffstat (limited to 'include/slang-com-ptr.h')
| -rw-r--r-- | include/slang-com-ptr.h | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/include/slang-com-ptr.h b/include/slang-com-ptr.h new file mode 100644 index 000000000..00cc9dbb1 --- /dev/null +++ b/include/slang-com-ptr.h @@ -0,0 +1,160 @@ +#ifndef SLANG_COM_PTR_H +#define SLANG_COM_PTR_H + +#include "slang-com-helper.h" + +#include <assert.h> +#include <cstddef> + +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 + +\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 +*/ + +// 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 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; } +#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. +#ifndef SLANG_COM_PTR_ENABLE_REF_OPERATOR + SLANG_FORCE_INLINE T** operator&() = delete; +#endif + + T* m_ptr; +}; + +//---------------------------------------------------------------------------- +template <typename T> +void ComPtr<T>::setNull() +{ + if (m_ptr) + { + ((Ptr)m_ptr)->release(); + m_ptr = nullptr; + } +} +//---------------------------------------------------------------------------- +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 |
