1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-14 04:29:15 +01:00

[util] Add private reference count to COM object

This can be used in case DXVK needs to keep a strong reference
to an object but may not expose that reference to the application.
This commit is contained in:
Philip Rebohle 2018-08-05 16:38:31 +02:00
parent 871c96b130
commit cdf6ffb9bc
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99

View File

@ -6,6 +6,22 @@
namespace dxvk {
/**
* \brief Reference-counted COM object
*
* This can serve as a templated base class for most
* COM objects. It implements AddRef and Release from
* \c IUnknown, and provides methods to increment and
* decrement private references which are not visible
* to the application.
*
* Having two reference counters is sadly necessary
* in order to not break games which steal internal
* references if the refefence count of an object is
+ greater than they expect. DXVK sometimes requires
* holding on to objects which the application wants
* to delete.
*/
template<typename... Base>
class ComObject : public Base... {
@ -14,21 +30,36 @@ namespace dxvk {
virtual ~ComObject() { }
ULONG STDMETHODCALLTYPE AddRef() {
return ++m_refCount;
ULONG refCount = m_refCount++;
if (refCount == 0ul)
AddRefPrivate();
return refCount;
}
ULONG STDMETHODCALLTYPE Release() {
ULONG refCount = --m_refCount;
if (refCount == 0) {
m_refCount += 0x80000000u;
if (refCount == 0ul)
ReleasePrivate();
return refCount;
}
void AddRefPrivate() {
++m_refPrivate;
}
void ReleasePrivate() {
if (--m_refPrivate == 0ul) {
m_refPrivate += 0x80000000;
delete this;
}
return refCount;
}
private:
std::atomic<ULONG> m_refCount = { 0ul };
std::atomic<ULONG> m_refCount = { 0ul };
std::atomic<ULONG> m_refPrivate = { 0ul };
};