19#include <QtCore/private/qglobal_p.h>
21#if defined(Q_OS_WIN) || defined(Q_QDOC)
23# include <QtCore/qt_windows.h>
29template <
typename... TInterfaces>
30struct QComObjectTraits
32 static constexpr bool isGuidOf(REFIID riid)
noexcept
34 return ((riid == __uuidof(TInterfaces)) || ...);
74template <
typename TFirstInterface,
typename... TAdditionalInterfaces>
75class QComObject :
public TFirstInterface,
public TAdditionalInterfaces...
78 STDMETHODIMP QueryInterface(REFIID riid,
void **ppvObject) override
83 if (riid == __uuidof(IUnknown)) {
84 *ppvObject =
static_cast<IUnknown *>(
static_cast<TFirstInterface *>(
this));
90 return tryQueryInterface<TFirstInterface, TAdditionalInterfaces...>(riid, ppvObject);
93 STDMETHODIMP_(ULONG) AddRef() override
95 return m_referenceCount.fetch_add(1, std::memory_order_relaxed) + 1;
98 STDMETHODIMP_(ULONG) Release() override
100 const LONG referenceCount = unref();
101 if (referenceCount == 0)
104 return referenceCount;
108 QComObject() =
default;
112 virtual ~QComObject() =
default;
115 std::atomic<LONG> m_referenceCount = 1;
117 [[nodiscard]] LONG unref()
119 const LONG referenceCount = m_referenceCount.fetch_sub(1, std::memory_order_release) - 1;
120 if (referenceCount == 0) {
124 std::atomic_thread_fence(std::memory_order_acquire);
126 return referenceCount;
130 template <
typename TInterface,
typename... TRest>
131 HRESULT tryQueryInterface(REFIID riid,
void **ppvObject)
133 if (QtPrivate::QComObjectTraits<TInterface>::isGuidOf(riid)) {
134 *ppvObject =
static_cast<TInterface *>(
this);
140 if constexpr (
sizeof...(TRest) > 0)
141 return tryQueryInterface<TRest...>(riid, ppvObject);
143 *ppvObject =
nullptr;
145 return E_NOINTERFACE;
149template <
typename Self,
typename... Interfaces>
150class QComObjectWithDeleteLater :
public QComObject<Interfaces...>
153 STDMETHODIMP_(ULONG) Release() override
155 const LONG referenceCount = QComObject<Interfaces...>::unref();
156 if (referenceCount == 0)
157 static_cast<Self *>(
this)->deleteLater();
159 return referenceCount;