winget-cli

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

COMStaticStorage.h (2759B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include <winrt/Windows.ApplicationModel.Core.h>
      5 #include <memory>
      6 #include <shared_mutex>
      7 #include <set>
      8 #include <string>
      9 #include <string_view>
     10 
     11 namespace AppInstaller::WinRT
     12 {
     13     // Contains registration for static storage so that they can be cleared.
     14     struct COMStaticStorageStatics
     15     {
     16         // Adds a static storage key to the set of known items.
     17         static void AddStaticStorageItem(const winrt::hstring& name, const winrt::Windows::Foundation::IInspectable& item);
     18 
     19         // Removes all known static storage items.
     20         static void ResetAll();
     21 
     22     private:
     23         COMStaticStorageStatics() = default;
     24 
     25         static COMStaticStorageStatics& Instance();
     26 
     27         winrt::slim_mutex m_lock;
     28         std::set<std::wstring> m_items;
     29     };
     30 
     31     // https://devblogs.microsoft.com/oldnewthing/20210215-00/?p=104865
     32     // Base class for an object that needs to live in the COM static store.
     33     // An object needs to use this if it has:
     34     //  - static lifetime
     35     //  - references to externally implemented COM objects
     36     //
     37     // Additionally, it should *not* contain references to WRL counted objects implemented by this module.
     38     // If it does, it will prevent the module from being unloaded until COM is uninitialized, which is often never.
     39     template <typename DataType>
     40     struct COMStaticStorageBase
     41     {
     42     private:
     43         struct DataHolder : public winrt::implements<DataHolder, winrt::Windows::Foundation::IInspectable>
     44         {
     45             std::shared_ptr<DataType> m_shared{ std::make_shared<DataType>() };
     46         };
     47 
     48         std::weak_ptr<DataType> m_weak;
     49         winrt::slim_mutex m_lock;
     50         winrt::hstring m_name;
     51 
     52     public:
     53         COMStaticStorageBase(std::wstring_view name) : m_name(name) {}
     54 
     55         std::shared_ptr<DataType> Get()
     56         {
     57             {
     58                 const std::shared_lock lock{ m_lock };
     59                 if (auto cached = m_weak.lock())
     60                 {
     61                     return cached;
     62                 }
     63             }
     64 
     65             auto value = winrt::make_self<DataHolder>();
     66 
     67             const winrt::slim_lock_guard lock{ m_lock };
     68             if (auto cached = m_weak.lock())
     69             {
     70                 return cached;
     71             }
     72 
     73             COMStaticStorageStatics::AddStaticStorageItem(m_name, value.as<winrt::Windows::Foundation::IInspectable>());
     74             m_weak = value->m_shared;
     75             return value->m_shared;
     76         }
     77 
     78         void Reset()
     79         {
     80             winrt::Windows::ApplicationModel::Core::CoreApplication::Properties().TryRemove(m_name);
     81         }
     82     };
     83 }