Making an agile version of a Windows Runtime delegate in C++/WinRT, part 7 - The Old New Thing
Skip to main content
Dev Blogs
AI
All .NET posts
.NET MAUI<br>ASP.NET Core<br>Blazor<br>Entity Framework
C++<br>C#<br>F#<br>TypeScript
NuGet<br>Servicing<br>.NET Blog in Chinese
Microsoft for Developers<br>Agent Framework<br>Develop from the cloud<br>Xcode<br>ISE Developer<br>TypeScript<br>PowerShell<br>Python<br>Java<br>Java Blog in Chinese<br>Go<br>Microsoft Edge Dev<br>Microsoft 365 Developer<br>Microsoft Entra Identity Developer<br>Microsoft Entra PowerShell
Visual Studio<br>Visual Studio Code<br>Aspire
All things Azure<br>Azure SDK<br>Azure VM Runtime Team<br>Microsoft Azure<br>Azure Cosmos DB<br>Azure DocumentDB<br>Azure Data Studio<br>Azure SQL<br>DevOps<br>DirectX<br>Microsoft Foundry<br>Power Platform
OData<br>Unified Data Model (IDEAs)
Windows Command Line<br>#ifdef Windows<br>Inside MSIX<br>MIDI and music<br>React Native<br>The Old New Thing<br>Windows Developer
Raymond Chen
Last time, we fixed the problem of creating a unique_ptr whose deleter’s constructor was might throw an exception. But we’re not out of the woods yet.
Let’s take another look at what we have:
if (d.try_as()) {<br>void* p;<br>if constexpr (std::is_reference_v) {<br>p = winrt::detach_abi(d);<br>} else {<br>winrt::copy_to_abi(d, p);<br>return<br>[p = std::unique_ptr(p, {}),<br>token = get_context_token()](auto&&...args) {<br>if (token == get_context_token()) {<br>std::remove_reference_t d;<br>winrt::copy_from_abi(d, p.get());<br>d(std::forward(args)...);<br>} else {<br>throw winrt::hresult_error(CO_E_NOT_SUPPORTED);<br>};
We had originally broken the rule that the unique_ptr(p) constructor requires that the deleter’s default constructor not throw an exception. We fixed it by constructing the deleter explicitly as a parameter, so that the unique_ptr constructor can move it into the stored deleter without an exception.
But wait, if an exception occurs in construction of the in_context_deleter, the raw pointer we created in the previous block will be leaked. It owns a reference count but doesn’t clean up in the case of an exception.
We can fix this by creating the deleter first.
if (d.try_as()) {<br>in_context_deleter del;<br>void* p;<br>if constexpr (std::is_reference_v) {<br>p = winrt::detach_abi(d);<br>} else {<br>winrt::copy_to_abi(d, p);<br>return<br>[p = std::unique_ptr(p, std::move(del)),<br>token = get_context_token()](auto&&...args) {<br>if (token == get_context_token()) {<br>std::remove_reference_t d;<br>winrt::copy_from_abi(d, p.get());<br>d(std::forward(args)...);<br>} else {<br>throw winrt::hresult_error(CO_E_NOT_SUPPORTED);<br>};
If there is an exception constructing the custom deleter, it happens before we initialze the raw pointer, so there is no leak of the reference owned by that raw pointer.
Okay, so are we done now?
Nope.
More next time.
Category<br>Old New Thing
Topics<br>Code
Share
Author
Raymond Chen
Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.
3 comments
Join the discussion.
Leave a commentCancel reply<br>Sign in
Code of Conduct
Sort by :
Newest
Newest<br>Popular<br>Oldest
@Raymond Chen:
I have a question unrelated to this topic and I hope you will investigate it when you have time.
You know that Microsoft.UniversalStore.HardwareWorkflow.SubmissionBuilder.dll (along with InfReader, Catalogs, Cabinets) used by Inf2Cat.exe?
Whoever wrote it must have been out of their god damn mind because the way it works is -- it parses all infs and driver files into a giant XML and uses that to generate the catalog file.
If you run it on an unpacked NVIDIA Display.Driver folder to regenerate the catalog it will create 260.52 MB XML file and spend north of 15 minutes creating a catalog because it is...<br>Read more@Raymond Chen:
I have a question unrelated to this topic and I hope you will investigate it when you have time.
You know that Microsoft.UniversalStore.HardwareWorkflow.SubmissionBuilder.dll (along with InfReader, Catalogs, Cabinets) used by Inf2Cat.exe?
Whoever wrote it must have been out of their god damn mind because the way it works is — it parses all infs and driver files into a giant XML and uses that to generate the catalog file.
If you run it on an unpacked NVIDIA Display.Driver folder to regenerate the catalog it will create 260.52 MB XML file and spend north of 15 minutes creating a catalog because it is using XML DOM as an update-able in-memory storage of inf keys and values instead of using custom structs and trie for example or at least an object model instead of XML DOM. And of course it runs on a single thread.
Inquiring minds want to know why this code, which is part of Windows DDK, uses such piss poor architecture, and how come that nobody noticed how bad / slow it is given...