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:
parent
871c96b130
commit
cdf6ffb9bc
@ -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 };
|
||||
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user