1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

ARA Host: Fix memory leak in ARAHostDocumentController

This commit is contained in:
attila 2022-07-16 18:38:32 +02:00
parent 9acfeece43
commit 07b96bc86d
4 changed files with 51 additions and 11 deletions

View file

@ -48,8 +48,21 @@ static ARA::ARAInterfaceConfiguration createInterfaceConfig (const ARA::ARAFacto
&assertFunction);
}
/* If the provided ARAFactory is not yet in use it constructs a new shared_ptr that will call the
provided onDelete function inside the custom deleter of this new shared_ptr instance.
The onDelete function is responsible for releasing the resources that guarantee the validity of
the wrapped ARAFactory*.
If however the ARAFactory is already in use the function will just return a copy of the already
existing shared_ptr and call the onDelete function immediately. This is to ensure that the
ARAFactory is only uninitialised when no plugin instance can be using it.
On both platforms the onDelete function is used to release resources that ensure that the module
providing the ARAFactory* remains loaded.
*/
static std::shared_ptr<const ARA::ARAFactory> getOrCreateARAFactory (const ARA::ARAFactory* ptr,
std::function<void (const ARA::ARAFactory*)> onDelete)
std::function<void()> onDelete)
{
JUCE_ASSERT_MESSAGE_THREAD
@ -58,14 +71,17 @@ static std::shared_ptr<const ARA::ARAFactory> getOrCreateARAFactory (const ARA::
auto& cachePtr = cache[ptr];
if (const auto obj = cachePtr.lock())
{
onDelete();
return obj;
}
const auto interfaceConfig = createInterfaceConfig (ptr);
ptr->initializeARAWithConfiguration (&interfaceConfig);
const auto obj = std::shared_ptr<const ARA::ARAFactory> (ptr, [deleter = std::move (onDelete)] (const ARA::ARAFactory* factory)
{
factory->uninitializeARA();
deleter (factory);
deleter();
});
cachePtr = obj;
return obj;

View file

@ -278,8 +278,18 @@ class ARAHostDocumentController::Impl
public:
Impl (ARAFactoryWrapper araFactoryIn,
std::unique_ptr<ARA::Host::DocumentControllerHostInstance>&& dcHostInstanceIn,
const ARA::ARADocumentControllerInstance* documentControllerInstance)
const ARA::ARADocumentControllerInstance* documentControllerInstance,
std::unique_ptr<ARA::Host::AudioAccessControllerInterface>&& audioAccessControllerIn,
std::unique_ptr<ARA::Host::ArchivingControllerInterface>&& archivingControllerIn,
std::unique_ptr<ARA::Host::ContentAccessControllerInterface>&& contentAccessControllerIn,
std::unique_ptr<ARA::Host::ModelUpdateControllerInterface>&& modelUpdateControllerIn,
std::unique_ptr<ARA::Host::PlaybackControllerInterface>&& playbackControllerIn)
: araFactory (std::move (araFactoryIn)),
audioAccessController (std::move (audioAccessControllerIn)),
archivingController (std::move (archivingControllerIn)),
contentAccessController (std::move (contentAccessControllerIn)),
modelUpdateController (std::move (modelUpdateControllerIn)),
playbackController (std::move (playbackControllerIn)),
dcHostInstance (std::move (dcHostInstanceIn)),
documentController (documentControllerInstance)
{
@ -300,16 +310,23 @@ public:
std::unique_ptr<ARA::Host::PlaybackControllerInterface>&& playbackController)
{
std::unique_ptr<ARA::Host::DocumentControllerHostInstance> dcHostInstance =
std::make_unique<ARA::Host::DocumentControllerHostInstance> (audioAccessController.release(),
archivingController.release(),
contentAccessController.release(),
modelUpdateController.release(),
playbackController.release());
std::make_unique<ARA::Host::DocumentControllerHostInstance> (audioAccessController.get(),
archivingController.get(),
contentAccessController.get(),
modelUpdateController.get(),
playbackController.get());
const auto documentProperties = makeARASizedStruct (&ARA::ARADocumentProperties::name, documentName.toRawUTF8());
if (auto* dci = araFactory.get()->createDocumentControllerWithDocument (dcHostInstance.get(), &documentProperties))
return std::make_unique<Impl> (std::move (araFactory), std::move (dcHostInstance), dci);
return std::make_unique<Impl> (std::move (araFactory),
std::move (dcHostInstance),
dci,
std::move (audioAccessController),
std::move (archivingController),
std::move (contentAccessController),
std::move (modelUpdateController),
std::move (playbackController));
return {};
}
@ -386,6 +403,13 @@ public:
private:
ARAFactoryWrapper araFactory;
std::unique_ptr<ARA::Host::AudioAccessControllerInterface> audioAccessController;
std::unique_ptr<ARA::Host::ArchivingControllerInterface> archivingController;
std::unique_ptr<ARA::Host::ContentAccessControllerInterface> contentAccessController;
std::unique_ptr<ARA::Host::ModelUpdateControllerInterface> modelUpdateController;
std::unique_ptr<ARA::Host::PlaybackControllerInterface> playbackController;
std::unique_ptr<ARA::Host::DocumentControllerHostInstance> dcHostInstance;
ARA::Host::DocumentController documentController;
};

View file

@ -488,7 +488,7 @@ static std::shared_ptr<const ARA::ARAFactory> getARAFactory (AudioUnitSharedPtr
{
jassert (audioUnitFactory.outFactory != nullptr);
return getOrCreateARAFactory (audioUnitFactory.outFactory,
[owningAuPtr = std::move (audioUnit)] (const ARA::ARAFactory*) {});
[owningAuPtr = std::move (audioUnit)]() {});
}
}
#else

View file

@ -1424,7 +1424,7 @@ static std::shared_ptr<const ARA::ARAFactory> getARAFactory (Steinberg::IPluginF
== Steinberg::kResultOk)
{
factory = getOrCreateARAFactory (source->getFactory(),
[source] (const ARA::ARAFactory*) { source->release(); });
[source]() { source->release(); });
return false;
}
jassert (source == nullptr);