From a7f7c21c782a9029b0db8e40273e15648fb74ff2 Mon Sep 17 00:00:00 2001 From: JohnMcPMS Date: Thu, 27 Jun 2024 15:33:58 -0700 Subject: [PATCH] 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. --- .../Public/winget/RepositorySource.h | 2 +- src/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 index cd44fe0c64..3bdcdb2822 100644 --- 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 m_backgroundUpdateInterval; bool m_installedPackageInformationOnly = false; - mutable PackageTrackingCatalog m_trackingCatalog; + mutable std::shared_ptr m_trackingCatalog; }; } diff --git a/src/AppInstallerRepositoryCore/RepositorySource.cpp b/src/AppInstallerRepositoryCore/RepositorySource.cpp index cef2a61891..5c279f4de0 100644 --- 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 currentTrackingCatalog = std::atomic_load(&m_trackingCatalog); + if (!currentTrackingCatalog) { - m_trackingCatalog = PackageTrackingCatalog::CreateForSource(*this); + std::shared_ptr newTrackingCatalog = std::make_shared(PackageTrackingCatalog::CreateForSource(*this)); + + if (std::atomic_compare_exchange_strong(&m_trackingCatalog, ¤tTrackingCatalog, newTrackingCatalog)) + { + currentTrackingCatalog = newTrackingCatalog; + } } - return m_trackingCatalog; + return *currentTrackingCatalog; } std::vector Source::GetCurrentSources()