yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
5.7 KiB153 linesraw
1#ifndef SLANG_COM_OBJECT_H
2#define SLANG_COM_OBJECT_H
3
4#include "slang-basic.h"
5
6#include <atomic>
7
8namespace Slang
9{
10
11/// A base class for COM interfaces that require atomic ref counting
12/// and are *NOT* derived from RefObject
13class ComBaseObject
14{
15public:
16    /// If assigned the the ref count is *NOT* copied
17    ComBaseObject& operator=(const ComBaseObject&) { return *this; }
18
19    /// Copy Ctor, does not copy ref count
20    ComBaseObject(const ComBaseObject&)
21        : m_refCount(0)
22    {
23    }
24
25    /// Default Ctor sets with no refs
26    ComBaseObject()
27        : m_refCount(0)
28    {
29    }
30
31    /// Dtor needs to be virtual to avoid needing to
32    /// Implement release for all derived types.
33    virtual ~ComBaseObject() {}
34
35protected:
36    inline uint32_t _releaseImpl();
37
38    std::atomic<uint32_t> m_refCount;
39};
40
41// ------------------------------------------------------------------
42inline uint32_t ComBaseObject::_releaseImpl()
43{
44    // Check there is a ref count to avoid underflow
45    SLANG_ASSERT(m_refCount != 0);
46    const uint32_t count = --m_refCount;
47    if (count == 0)
48    {
49        delete this;
50    }
51    return count;
52}
53
54#define SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE                                                    \
55    SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) \
56        SLANG_OVERRIDE                                                                             \
57    {                                                                                              \
58        void* intf = getInterface(uuid);                                                           \
59        if (intf)                                                                                  \
60        {                                                                                          \
61            ++m_refCount;                                                                          \
62            *outObject = intf;                                                                     \
63            return SLANG_OK;                                                                       \
64        }                                                                                          \
65        return SLANG_E_NO_INTERFACE;                                                               \
66    }
67#define SLANG_COM_BASE_IUNKNOWN_ADD_REF                         \
68    SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE \
69    {                                                           \
70        return ++m_refCount;                                    \
71    }
72#define SLANG_COM_BASE_IUNKNOWN_RELEASE                          \
73    SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE \
74    {                                                            \
75        return _releaseImpl();                                   \
76    }
77#define SLANG_COM_BASE_IUNKNOWN_ALL         \
78    SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE \
79    SLANG_COM_BASE_IUNKNOWN_ADD_REF         \
80    SLANG_COM_BASE_IUNKNOWN_RELEASE
81
82
83/// COM object that derives from RefObject
84class ComObject : public RefObject
85{
86protected:
87    std::atomic<uint32_t> comRefCount;
88
89public:
90    ComObject()
91        : comRefCount(0)
92    {
93    }
94    ComObject(const ComObject& rhs)
95        : RefObject(rhs), comRefCount(0)
96    {
97    }
98
99    ComObject& operator=(const ComObject&) { return *this; }
100
101    virtual void comFree() {}
102
103    uint32_t addRefImpl()
104    {
105        auto oldRefCount = comRefCount++;
106        if (oldRefCount == 0)
107            addReference();
108        return oldRefCount + 1;
109    }
110
111    uint32_t releaseImpl()
112    {
113        auto oldRefCount = comRefCount--;
114        if (oldRefCount == 1)
115        {
116            comFree();
117            releaseReference();
118        }
119        return oldRefCount - 1;
120    }
121};
122
123#define SLANG_COM_OBJECT_IUNKNOWN_QUERY_INTERFACE                                                  \
124    SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) \
125        SLANG_OVERRIDE                                                                             \
126    {                                                                                              \
127        void* intf = getInterface(uuid);                                                           \
128        if (intf)                                                                                  \
129        {                                                                                          \
130            addRef();                                                                              \
131            *outObject = intf;                                                                     \
132            return SLANG_OK;                                                                       \
133        }                                                                                          \
134        return SLANG_E_NO_INTERFACE;                                                               \
135    }
136#define SLANG_COM_OBJECT_IUNKNOWN_ADD_REF                       \
137    SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE \
138    {                                                           \
139        return addRefImpl();                                    \
140    }
141#define SLANG_COM_OBJECT_IUNKNOWN_RELEASE                        \
142    SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE \
143    {                                                            \
144        return releaseImpl();                                    \
145    }
146#define SLANG_COM_OBJECT_IUNKNOWN_ALL         \
147    SLANG_COM_OBJECT_IUNKNOWN_QUERY_INTERFACE \
148    SLANG_COM_OBJECT_IUNKNOWN_ADD_REF         \
149    SLANG_COM_OBJECT_IUNKNOWN_RELEASE
150
151} // namespace Slang
152
153#endif