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