mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
ComSmartPtr: Make ownership more explicit
COM objects now always start with a refcount of 1, as is convention.
This commit is contained in:
parent
fe9fc0c0e6
commit
1f9ba0682c
12 changed files with 78 additions and 47 deletions
|
|
@ -623,9 +623,8 @@ private:
|
|||
|
||||
if (audioSessionControl != nullptr)
|
||||
{
|
||||
sessionEventCallback = new SessionEventCallback (*this);
|
||||
sessionEventCallback = becomeComSmartPtrOwner (new SessionEventCallback (*this));
|
||||
audioSessionControl->RegisterAudioSessionNotification (sessionEventCallback);
|
||||
sessionEventCallback->Release(); // (required because ComBaseClassHelper objects are constructed with a ref count of 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1831,7 +1830,7 @@ private:
|
|||
{
|
||||
public:
|
||||
explicit ChangeNotificationClient (WASAPIAudioIODeviceType* d)
|
||||
: ComBaseClassHelper (0), device (d) {}
|
||||
: device (d) {}
|
||||
|
||||
JUCE_COMRESULT OnDeviceAdded (LPCWSTR) override { return notify(); }
|
||||
JUCE_COMRESULT OnDeviceRemoved (LPCWSTR) override { return notify(); }
|
||||
|
|
@ -1859,10 +1858,10 @@ private:
|
|||
static String getDefaultEndpoint (IMMDeviceEnumerator* enumerator, bool forCapture)
|
||||
{
|
||||
String s;
|
||||
IMMDevice* dev = nullptr;
|
||||
ComSmartPtr<IMMDevice> dev;
|
||||
|
||||
if (check (enumerator->GetDefaultAudioEndpoint (forCapture ? eCapture : eRender,
|
||||
eMultimedia, &dev)))
|
||||
eMultimedia, dev.resetAndGetPointerAddress())))
|
||||
{
|
||||
WCHAR* deviceId = nullptr;
|
||||
|
||||
|
|
@ -1871,8 +1870,6 @@ private:
|
|||
s = deviceId;
|
||||
CoTaskMemFree (deviceId);
|
||||
}
|
||||
|
||||
dev->Release();
|
||||
}
|
||||
|
||||
return s;
|
||||
|
|
@ -1886,7 +1883,7 @@ private:
|
|||
if (! check (enumerator.CoCreateInstance (__uuidof (MMDeviceEnumerator))))
|
||||
return {};
|
||||
|
||||
notifyClient = new ChangeNotificationClient (this);
|
||||
notifyClient = becomeComSmartPtrOwner (new ChangeNotificationClient (this));
|
||||
enumerator->RegisterEndpointNotificationCallback (notifyClient);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class JuceIStream final : public ComBaseClassHelper<IStream>
|
|||
{
|
||||
public:
|
||||
JuceIStream (InputStream& in) noexcept
|
||||
: ComBaseClassHelper (0), source (in)
|
||||
: source (in)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +153,7 @@ public:
|
|||
HRESULT hr = wmCreateSyncReader (nullptr, WMT_RIGHT_PLAYBACK, wmSyncReader.resetAndGetPointerAddress());
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
hr = wmSyncReader->OpenStream (new JuceIStream (*input));
|
||||
hr = wmSyncReader->OpenStream (becomeComSmartPtrOwner (new JuceIStream (*input)));
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,30 +103,27 @@ template <class ComClass>
|
|||
class ComSmartPtr
|
||||
{
|
||||
public:
|
||||
ComSmartPtr() noexcept {}
|
||||
ComSmartPtr (ComClass* obj) : p (obj) { if (p) p->AddRef(); }
|
||||
ComSmartPtr (const ComSmartPtr& other) : p (other.p) { if (p) p->AddRef(); }
|
||||
~ComSmartPtr() { release(); }
|
||||
ComSmartPtr() noexcept = default;
|
||||
ComSmartPtr (std::nullptr_t) noexcept {}
|
||||
|
||||
template <typename U>
|
||||
ComSmartPtr (const ComSmartPtr<U>& other) : ComSmartPtr (other, true) {}
|
||||
ComSmartPtr (const ComSmartPtr& other) : ComSmartPtr (other, true) {}
|
||||
|
||||
~ComSmartPtr() noexcept { release(); }
|
||||
|
||||
template <typename U>
|
||||
ComSmartPtr& operator= (const ComSmartPtr<U>& newP) { ComSmartPtr copy { newP }; std::swap (copy.p, p); return *this; }
|
||||
ComSmartPtr& operator= (const ComSmartPtr& newP) { ComSmartPtr copy { newP }; std::swap (copy.p, p); return *this; }
|
||||
|
||||
operator ComClass*() const noexcept { return p; }
|
||||
ComClass& operator*() const noexcept { return *p; }
|
||||
ComClass* operator->() const noexcept { return p; }
|
||||
|
||||
ComSmartPtr& operator= (ComClass* const newP)
|
||||
{
|
||||
if (newP != nullptr) newP->AddRef();
|
||||
release();
|
||||
p = newP;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ComSmartPtr& operator= (const ComSmartPtr& newP) { return operator= (newP.p); }
|
||||
|
||||
// Releases and nullifies this pointer and returns its address
|
||||
ComClass** resetAndGetPointerAddress()
|
||||
{
|
||||
release();
|
||||
p = nullptr;
|
||||
return &p;
|
||||
}
|
||||
|
||||
|
|
@ -160,30 +157,70 @@ public:
|
|||
if (QueryInterface (destObject) == S_OK)
|
||||
return destObject;
|
||||
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
/** Increments refcount. */
|
||||
static auto addOwner (ComClass* t)
|
||||
{
|
||||
return ComSmartPtr (t, true);
|
||||
}
|
||||
|
||||
/** Does not initially increment refcount; assumes t has a positive refcount. */
|
||||
static auto becomeOwner (ComClass* t)
|
||||
{
|
||||
return ComSmartPtr (t, false);
|
||||
}
|
||||
|
||||
private:
|
||||
ComClass* p = nullptr;
|
||||
template <typename U>
|
||||
friend class ComSmartPtr;
|
||||
|
||||
void release() { if (p != nullptr) p->Release(); }
|
||||
ComSmartPtr (ComClass* object, bool autoAddRef) noexcept
|
||||
: p (object)
|
||||
{
|
||||
if (p != nullptr && autoAddRef)
|
||||
p->AddRef();
|
||||
}
|
||||
|
||||
void release()
|
||||
{
|
||||
if (auto* q = std::exchange (p, nullptr))
|
||||
q->Release();
|
||||
}
|
||||
|
||||
ComClass** operator&() noexcept; // private to avoid it being used accidentally
|
||||
|
||||
ComClass* p = nullptr;
|
||||
};
|
||||
|
||||
/** Increments refcount. */
|
||||
template <class ObjectType>
|
||||
auto addComSmartPtrOwner (ObjectType* t)
|
||||
{
|
||||
return ComSmartPtr<ObjectType>::addOwner (t);
|
||||
}
|
||||
|
||||
/** Does not initially increment refcount; assumes t has a positive refcount. */
|
||||
template <class ObjectType>
|
||||
auto becomeComSmartPtrOwner (ObjectType* t)
|
||||
{
|
||||
return ComSmartPtr<ObjectType>::becomeOwner (t);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
template <class First, class... ComClasses>
|
||||
class ComBaseClassHelperBase : public First, public ComClasses...
|
||||
{
|
||||
public:
|
||||
ComBaseClassHelperBase (unsigned int initialRefCount) : refCount (initialRefCount) {}
|
||||
ComBaseClassHelperBase() = default;
|
||||
virtual ~ComBaseClassHelperBase() = default;
|
||||
|
||||
ULONG STDMETHODCALLTYPE AddRef() override { return ++refCount; }
|
||||
ULONG STDMETHODCALLTYPE Release() override { auto r = --refCount; if (r == 0) delete this; return r; }
|
||||
|
||||
protected:
|
||||
ULONG refCount;
|
||||
ULONG refCount = 1;
|
||||
|
||||
JUCE_COMRESULT QueryInterface (REFIID refId, void** result) override
|
||||
{
|
||||
|
|
@ -212,8 +249,7 @@ template <class... ComClasses>
|
|||
class ComBaseClassHelper : public ComBaseClassHelperBase<ComClasses...>
|
||||
{
|
||||
public:
|
||||
explicit ComBaseClassHelper (unsigned int initialRefCount = 1)
|
||||
: ComBaseClassHelperBase<ComClasses...> (initialRefCount) {}
|
||||
ComBaseClassHelper() = default;
|
||||
|
||||
JUCE_COMRESULT QueryInterface (REFIID refId, void** result) override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ namespace DirectWriteTypeLayout
|
|||
{
|
||||
public:
|
||||
CustomDirectWriteTextRenderer (IDWriteFontCollection& fonts, const AttributedString& as)
|
||||
: ComBaseClassHelper (0),
|
||||
attributedString (as),
|
||||
: attributedString (as),
|
||||
fontCollection (fonts)
|
||||
{
|
||||
}
|
||||
|
|
@ -432,7 +431,7 @@ namespace DirectWriteTypeLayout
|
|||
layout.ensureStorageAllocated ((int) actualLineCount);
|
||||
|
||||
{
|
||||
ComSmartPtr<CustomDirectWriteTextRenderer> textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text));
|
||||
auto textRenderer = becomeComSmartPtrOwner (new CustomDirectWriteTextRenderer (fontCollection, text));
|
||||
hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ public:
|
|||
{
|
||||
jassert (path.isEmpty()); // we might need to apply a transform to the path, so this must be empty
|
||||
auto glyphIndex = (UINT16) glyphNumber;
|
||||
ComSmartPtr<PathGeometrySink> pathGeometrySink (new PathGeometrySink());
|
||||
auto pathGeometrySink = becomeComSmartPtrOwner (new PathGeometrySink());
|
||||
|
||||
dwFontFace->GetGlyphRunOutline (1024.0f, &glyphIndex, nullptr, nullptr,
|
||||
1, false, false, pathGeometrySink);
|
||||
|
|
@ -296,7 +296,7 @@ private:
|
|||
|
||||
struct PathGeometrySink final : public ComBaseClassHelper<IDWriteGeometrySink>
|
||||
{
|
||||
PathGeometrySink() : ComBaseClassHelper (0) {}
|
||||
PathGeometrySink() = default;
|
||||
|
||||
void STDMETHODCALLTYPE AddBeziers (const D2D1_BEZIER_SEGMENT* beziers, UINT beziersCount) noexcept override
|
||||
{
|
||||
|
|
|
|||
|
|
@ -151,8 +151,7 @@ static auto roleToControlTypeId (AccessibilityRole roleType)
|
|||
|
||||
//==============================================================================
|
||||
AccessibilityNativeHandle::AccessibilityNativeHandle (AccessibilityHandler& handler)
|
||||
: ComBaseClassHelper (0),
|
||||
accessibilityHandler (handler)
|
||||
: accessibilityHandler (handler)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class AccessibilityHandler::AccessibilityNativeImpl
|
|||
{
|
||||
public:
|
||||
explicit AccessibilityNativeImpl (AccessibilityHandler& owner)
|
||||
: accessibilityElement (new AccessibilityNativeHandle (owner))
|
||||
: accessibilityElement (becomeComSmartPtrOwner (new AccessibilityNativeHandle (owner)))
|
||||
{
|
||||
++providerCount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class UIAProviderBase
|
|||
{
|
||||
public:
|
||||
explicit UIAProviderBase (AccessibilityNativeHandle* nativeHandleIn)
|
||||
: nativeHandle (nativeHandleIn)
|
||||
: nativeHandle (addComSmartPtrOwner (nativeHandleIn))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ private:
|
|||
public:
|
||||
UIATextRangeProvider (UIATextProvider& textProvider, Range<int> range)
|
||||
: UIAProviderBase (textProvider.getHandler().getNativeImplementation()),
|
||||
owner (&textProvider),
|
||||
owner (addComSmartPtrOwner (&textProvider)),
|
||||
selectionRange (range)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ private:
|
|||
{
|
||||
HWND hwnd = nullptr;
|
||||
|
||||
if (auto window = ComSmartPtr<IFileDialog> { d }.getInterface<IOleWindow>())
|
||||
if (auto window = addComSmartPtrOwner (d).getInterface<IOleWindow>())
|
||||
window->GetWindow (&hwnd);
|
||||
|
||||
ScopedLock lock (owner.deletingDialog);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace ActiveXHelpers
|
|||
JUCE_COMRESULT GetBorder (LPRECT) override { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT RequestBorderSpace (LPCBORDERWIDTHS) override { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT SetBorderSpace (LPCBORDERWIDTHS) override { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT SetActiveObject (IOleInPlaceActiveObject* a, LPCOLESTR) override { activeObject = a; return S_OK; }
|
||||
JUCE_COMRESULT SetActiveObject (IOleInPlaceActiveObject* a, LPCOLESTR) override { activeObject = addComSmartPtrOwner (a); return S_OK; }
|
||||
JUCE_COMRESULT InsertMenus (HMENU, LPOLEMENUGROUPWIDTHS) override { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT SetMenu (HMENU, HOLEMENU, HWND) override { return S_OK; }
|
||||
JUCE_COMRESULT RemoveMenus (HMENU) override { return E_NOTIMPL; }
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ struct CameraDevice::Pimpl : public ChangeBroadcaster
|
|||
sampleGrabber->SetMediaType (&mt);
|
||||
}
|
||||
|
||||
callback = new GrabberCallback (*this);
|
||||
callback = becomeComSmartPtrOwner (new GrabberCallback (*this));
|
||||
hr = sampleGrabber->SetCallback (callback, 1);
|
||||
|
||||
hr = graphBuilder->AddFilter (sampleGrabberBase, _T ("Sample Grabber"));
|
||||
|
|
@ -536,8 +536,8 @@ struct CameraDevice::Pimpl : public ChangeBroadcaster
|
|||
|
||||
struct GrabberCallback : public ComBaseClassHelperBase<ComTypes::ISampleGrabberCB>
|
||||
{
|
||||
GrabberCallback (Pimpl& p)
|
||||
: ComBaseClassHelperBase (0), owner (p) {}
|
||||
explicit GrabberCallback (Pimpl& p)
|
||||
: owner (p) {}
|
||||
|
||||
JUCE_COMRESULT QueryInterface (REFIID refId, void** result) override
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue