commit a7f7c21c782a9029b0db8e40273e15648fb74ff2
parent 986f2409fdeed2e46b3c36a8e346708363312a38
Author: JohnMcPMS <johnmcp@microsoft.com>
Date: Thu, 27 Jun 2024 15:33:58 -0700
Use atomic functions to ensure single initialization of tracking catalog (#4592)
Fixes #4587
## Change
Hold the tracking catalog object in a `shared_ptr` and use the atomic
functions to ensure that only one thread can initialize it.
Diffstat:
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h b/src/AppInstallerRepositoryCore/Public/winget/RepositorySource.h
@@ -344,6 +344,6 @@ namespace AppInstaller::Repository
bool m_isComposite = false;
std::optional<TimeSpan> m_backgroundUpdateInterval;
bool m_installedPackageInformationOnly = false;
- mutable PackageTrackingCatalog m_trackingCatalog;
+ mutable std::shared_ptr<PackageTrackingCatalog> m_trackingCatalog;
};
}
diff --git a/src/AppInstallerRepositoryCore/RepositorySource.cpp b/src/AppInstallerRepositoryCore/RepositorySource.cpp
@@ -983,12 +983,19 @@ namespace AppInstaller::Repository
PackageTrackingCatalog Source::GetTrackingCatalog() const
{
- if (!m_trackingCatalog)
+ // With C++20, consider removing the shared_ptr here and making the one inside PackageTrackingCatalog atomic.
+ std::shared_ptr<PackageTrackingCatalog> currentTrackingCatalog = std::atomic_load(&m_trackingCatalog);
+ if (!currentTrackingCatalog)
{
- m_trackingCatalog = PackageTrackingCatalog::CreateForSource(*this);
+ std::shared_ptr<PackageTrackingCatalog> newTrackingCatalog = std::make_shared<PackageTrackingCatalog>(PackageTrackingCatalog::CreateForSource(*this));
+
+ if (std::atomic_compare_exchange_strong(&m_trackingCatalog, ¤tTrackingCatalog, newTrackingCatalog))
+ {
+ currentTrackingCatalog = newTrackingCatalog;
+ }
}
- return m_trackingCatalog;
+ return *currentTrackingCatalog;
}
std::vector<SourceDetails> Source::GetCurrentSources()