{"id":111118,"date":"2025-04-25T07:00:00","date_gmt":"2025-04-25T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111118"},"modified":"2025-04-25T06:50:02","modified_gmt":"2025-04-25T13:50:02","slug":"20250425-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250425-00\/?p=111118","title":{"rendered":"If we can have <CODE>std::atomic&lt;std::shared_ptr&gt;<\/CODE>, why not <CODE>std::atomic&lt;com_ptr&gt;<\/CODE>?"},"content":{"rendered":"<p>Some time ago, we peeked <a title=\"Inside STL: The atomic shared_ptr\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20241219-00\/?p=110663\"> inside the atomic shared_ptr<\/a> to see how it worked. Can we apply these same principles to create <a title=\"Since std::atomic&lt;std::shared_ptr&lt;T&gt;&gt; exists, would it make sense to also have atomic versions of C++\/WinRT projection types and winrt::com_ptr&lt;T&gt;?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240717-00\/?p=109975&amp;commentid=141701#comment-141701\"> an atomic <code>com_ptr<\/code><\/a>?<\/p>\n<p>Recall that the atomic shared_ptr operates by using the bottom bit of the control block pointer as a lock flag, so that nobody can change the value while we&#8217;re copying the pointer and incrementing the reference count. Can we do this with a <code>com_ptr<\/code>?<\/p>\n<p>We could use the same trick of using the bottom bit of the raw COM pointer as a lock flag. This is acceptable because COM pointers must be pointer-aligned (since they point to a vtable), so we know that the bottom bit of a valid COM pointer is clear. However, we run into trouble when trying to increment the reference count: The call to <code>IUnknown::<wbr \/>AddRef<\/code> happens while the lock is held, but the <code>AddRef<\/code> is a call out to external code, and we don&#8217;t know what it&#8217;s going to do. We know what it&#8217;s <i>supposed<\/i> to do (namely, increment the reference count), but it may take a circuitous route to get there, including passing through aggregated controlling unknowns, tear-off stubs, <a title=\"Notes on COM aggregation: How do you implement tear-offs in an aggregated object?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220211-00\/?p=106246\"> tear-offs of aggregated objects<\/a>, <a title=\"Notes on COM aggregation: Obtaining a pointer to your aggregated partner without introducing a reference cycle\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220210-00\/?p=106243\"> weak outer pointers<\/a>, and other fanciful characters.<\/p>\n<p>We know that holding a lock while calling out to external code is a source of deadlocks, so holding a lock while calling out to a mystery implementation of <code>IUnknown::<wbr \/>AddRef<\/code> is probably not a good idea.<\/p>\n<p>Sorry.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Controlling the reference count.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-111118","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Controlling the reference count.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=111118"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111118\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=111118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}