mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22: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:
parent
871c96b130
commit
cdf6ffb9bc
@ -6,6 +6,22 @@
|
|||||||
|
|
||||||
namespace dxvk {
|
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>
|
template<typename... Base>
|
||||||
class ComObject : public Base... {
|
class ComObject : public Base... {
|
||||||
|
|
||||||
@ -14,21 +30,36 @@ namespace dxvk {
|
|||||||
virtual ~ComObject() { }
|
virtual ~ComObject() { }
|
||||||
|
|
||||||
ULONG STDMETHODCALLTYPE AddRef() {
|
ULONG STDMETHODCALLTYPE AddRef() {
|
||||||
return ++m_refCount;
|
ULONG refCount = m_refCount++;
|
||||||
|
if (refCount == 0ul)
|
||||||
|
AddRefPrivate();
|
||||||
|
return refCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG STDMETHODCALLTYPE Release() {
|
ULONG STDMETHODCALLTYPE Release() {
|
||||||
ULONG refCount = --m_refCount;
|
ULONG refCount = --m_refCount;
|
||||||
if (refCount == 0) {
|
if (refCount == 0ul)
|
||||||
m_refCount += 0x80000000u;
|
ReleasePrivate();
|
||||||
|
return refCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AddRefPrivate() {
|
||||||
|
++m_refPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ReleasePrivate() {
|
||||||
|
if (--m_refPrivate == 0ul) {
|
||||||
|
m_refPrivate += 0x80000000;
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
return refCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::atomic<ULONG> m_refCount = { 0ul };
|
std::atomic<ULONG> m_refCount = { 0ul };
|
||||||
|
std::atomic<ULONG> m_refPrivate = { 0ul };
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user