winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/AppInstallerRepositoryCore/Public/winget/RepositorySource.h | 2+-
Msrc/AppInstallerRepositoryCore/RepositorySource.cpp | 13++++++++++---
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, &currentTrackingCatalog, newTrackingCatalog)) + { + currentTrackingCatalog = newTrackingCatalog; + } } - return m_trackingCatalog; + return *currentTrackingCatalog; } std::vector<SourceDetails> Source::GetCurrentSources()