This article discusses implementing an agile Windows Runtime delegate in C++/WinRT, focusing on using CoGetContextToken to compare context tokens for efficiency instead of comparing COM objects.
<p>Last time, we wrote a wrapper delegate that <a title="Making an agile version of a Windows Runtime delegate in C++/WinRT, part 4" href="https://devblogs.microsoft.com/oldnewthing/20260722-00/?p=112552"> checked whether the context it was being invoked from matched the context it was captured from</a>.</p>
<pre> if (d.try_as<::INoMarshal>()) {
return [d = std::forward<Delegate>(d),
context = winrt::capture<IContextCallback>(CoGetObjectContext)](auto&&...args) {
if (context == winrt::capture<IContextCallback>(CoGetObjectContext)) {
d(std::forward<decltype(args)>(args)...);
} else {
throw winrt::hresult_error(CO_E_NOT_SUPPORTED);
}
};
}
</pre>
<p>We did this by comparing context objects.</p>
<p>This obtains the current object context in order to compare it with the original one, and that means an internal <code>AddRef</code>, and then we have to explicitly <code>Release</code> it.</p>
<p>But there’s a way to do this without having to obtain any objects.</p>
<p>The <code>CoGetContextToken</code> function gives you an integer that uniquely identifies a live context object. You can then compare integers instead of having to compare COM objects.</p>
<p>Note that the context must be live. Once you allow the context to destruct, the value might be reused. (You’re already used to this. Process and thread IDs work the same way: They remain unique as long as they are running or you still have a reference to them by a <code>HANDLE</code>.)</p>
<p>Since we are keeping the context alive by the <code>IContextCallback</code> returned by <code>CoGetObjectContext</code>, we can pair that with a context token to make for faster checks in the future.</p>
<pre><span style="border: solid 1px currentcolor; border-bottom: none;">ULONG_PTR get_context_token() </span>
<span style="border: 1px currentcolor; border-style: none solid;">{ </span>
<span style="border: 1px currentcolor; border-style: none solid;"> ULONG_PTR token; </span>
<span style="border: 1px currentcolor; border-style: none solid;"> winrt::check_hresult(CoGetContextToken(&token));</span>
<span style="border: 1px currentcolor; border-style: none solid;"> return token; </span>
<span style="border: solid 1px currentcolor; border-top: none;">} </span>
if (d.try_as<::INoMarshal>()) {
return [d = std::forward<Delegate>(d),
context = winrt::capture<IContextCallback>(CoGetObjectContext),
<span style="border: solid 1px currentcolor;">token = get_context_token()</span>](auto&&...args) {
if (<span style="border: solid 1px currentcolor;">token == get_context_token()</span>) {
d(std::forward<decltype(args)>(args)...);
} else {
throw winrt::hresult_error(CO_E_NOT_SUPPORTED);
}
};
}
</pre>
<p>Are we done?</p>
<p>Of course not!</p>
<p>There’s a flaw in the above code. More next time.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260723-00/?p=112560">Making an agile version of a Windows Runtime delegate in C++/WinRT, part 4</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# Making an agile version of a Windows Runtime delegate in C++/WinRT, part 4 - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20260723-00?p=112560](https://devblogs.microsoft.com/oldnewthing/20260723-00?p=112560)
Last time, we wrote a wrapper delegate that[checked whether the context it was being invoked from matched the context it was captured from](https://devblogs.microsoft.com/oldnewthing/20260722-00/?p=112552)\.
```
if (d.try_as<::INoMarshal>()) {
return [d = std::forward<Delegate>(d),
context = winrt::capture<IContextCallback>(CoGetObjectContext)](auto&&...args) {
if (context == winrt::capture<IContextCallback>(CoGetObjectContext)) {
d(std::forward<decltype(args)>(args)...);
} else {
throw winrt::hresult_error(CO_E_NOT_SUPPORTED);
}
};
}
```
We did this by comparing context objects\.
This obtains the current object context in order to compare it with the original one, and that means an internal`AddRef`, and then we have to explicitly`Release`it\.
But there’s a way to do this without having to obtain any objects\.
The`CoGetContextToken`function gives you an integer that uniquely identifies a live context object\. You can then compare integers instead of having to compare COM objects\.
Note that the context must be live\. Once you allow the context to destruct, the value might be reused\. \(You’re already used to this\. Process and thread IDs work the same way: They remain unique as long as they are running or you still have a reference to them by a`HANDLE`\.\)
Since we are keeping the context alive by the`IContextCallback`returned by`CoGetObjectContext`, we can pair that with a context token to make for faster checks in the future\.
```
ULONG_PTR get_context_token()
{
ULONG_PTR token;
winrt::check_hresult(CoGetContextToken(&token));
return token;
}
if (d.try_as<::INoMarshal>()) {
return [d = std::forward<Delegate>(d),
context = winrt::capture<IContextCallback>(CoGetObjectContext),
token = get_context_token()](auto&&...args) {
if (token == get_context_token()) {
d(std::forward<decltype(args)>(args)...);
} else {
throw winrt::hresult_error(CO_E_NOT_SUPPORTED);
}
};
}
```
Are we done?
Of course not\!
There’s a flaw in the above code\. More next time\.
### Category
### Topics
## Author

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\.
This article continues a series on implementing agile delegates in C++/WinRT, addressing the issue of destructing non-agile delegates in the correct context using a custom deleter and IContextCallback.
This blog post discusses handling Windows Runtime delegates that implement the INoMarshal interface in C++/WinRT, providing an agile delegate wrapper that checks the calling context to avoid marshaling errors.
This article explains how to create an agile version of a Windows Runtime delegate in C++/WinRT by wrapping the delegate in an agile_ref, with a promise of more details in part 2.
Raymond Chen continues his series on building an agile Windows Runtime delegate in C++/WinRT, comparing how C++/WinRT, C++/CX, and WRL handle non-marshalable delegates and agile reference creation.
The article discusses a fix for exception safety in C++/WinRT when creating an agile delegate, addressing the issue of unspecified lambda capture construction order to prevent reference leaks.