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 }