[MS] Making an agile version of a Windows Runtime delegate in C++/WinRT, part 7 - devamazonaws.blogspot.com
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<::INoMarshal>()) {
void* p;
if constexpr (std::is_reference_v<Delegate>) {
p = winrt::detach_abi(d);
} else {
winrt::copy_to_abi(d, p);
}
return
[p = std::unique_ptr<void, in_context_deleter>(p, {}),
token = get_context_token()](auto&&...args) {
if (token == get_context_token()) {
std::remove_reference_t<Delegate> d;
winrt::copy_from_abi(d, p.get());
d(std::forward<decltype(args)>(args)...);
} else {
throw winrt::hresult_error(CO_E_NOT_SUPPORTED);
}
};
}
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_, 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<::INoMarshal>()) {
in_context_deleter del;
void* p;
if constexpr (std::is_reference_v<Delegate>) {
p = winrt::detach_abi(d);
} else {
winrt::copy_to_abi(d, p);
}
return
[p = std::unique_ptr<void, in_context_deleter>(p, std::move(del)),
token = get_context_token()](auto&&...args) {
if (token == get_context_token()) {
std::remove_reference_t<Delegate> d;
winrt::copy_from_abi(d, p.get());
d(std::forward<decltype(args)>(args)...);
} else {
throw winrt::hresult_error(CO_E_NOT_SUPPORTED);
}
};
}
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.
Post Updated on July 28, 2026 at 03:00PM
Thanks for reading
from devamazonaws.blogspot.com
Comments
Post a Comment