{"id":109461,"date":"2024-02-28T07:00:00","date_gmt":"2024-02-28T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109461"},"modified":"2024-02-28T09:07:41","modified_gmt":"2024-02-28T17:07:41","slug":"20240228-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240228-00\/?p=109461","title":{"rendered":"On the whole idea of giving away a reference to yourself at destruction"},"content":{"rendered":"<p>One of the responses to my discussion of <a title=\"How can I give away a COM reference just before my object destructs?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240125-00\/?p=109317\"> how to give away a COM reference to yourself at destruction<\/a> was roughly &#8220;The crazy convolutions required to accomplish this demonstrate how COM is a disaster.&#8221;<\/p>\n<p>Well, some people may feel that COM is a disaster, but at least this specific piece of COM isn&#8217;t a disaster.<\/p>\n<p>In a non-disastrous language, say, C++ with the standard library,\u00b9 if somebody asked you, &#8220;How do I run some code when my <code>shared_ptr<\/code> reference count drops to 1?&#8221;, the answer is simple: You can&#8217;t do it! C++&#8217;s <code>shared_ptr<\/code> does not give you that level of access to the internal reference count. You can peek at the reference count by asking for the <code>use_count()<\/code>, but that is necessarily just an approximation due to multithreading. Even knowing that the use count is 1 doesn&#8217;t prove that you have the last <code>shared_ptr<\/code>. The reference count might go back up to 2 due to a race against a <code>weak_ptr::lock()<\/code>, and your attempt to detect when the reference count has dropped to 1 has failed.<\/p>\n<p>In C# and Java, you are allowed to rescue an object in its finalizer, known as <i>object resurrection<\/i>. Java weak references expire before the object is submitted for finalization, so even if you rescue the object in its finalizer, it&#8217;s too late to preserve the weak references. C# weak references default to Java style, but you can ask for a &#8220;long&#8221; weak reference which retains its connection to the object even past finalization. Unfortunately, the object cannot control the types of weak references that people create, and if somebody creates a long weak reference, then they can access your object while it is finalizing! That is likely to result in unhappiness if the finalizer cleaned up external resources (that being the primary purpose of finalizers), since the object no longer has its external resources and consequently is unable to perform any useful operations.<\/p>\n<p>Maybe the real problem is the design that required an object to hand out a reference to itself at destruction. That&#8217;s what forced us into the weird contortions. But at least it&#8217;s <i>possible<\/i> with COM. That&#8217;s more than can be said for other frameworks.<\/p>\n<p><b>Bonus chatter<\/b>: I perhaps did not note clearly enough that the intended design of the <code>Closed<\/code> event is that it is raised only the first time the last application reference is released. If the application rescues the object in its <code>Closed<\/code> event handler, and then subsequently releases the rescued object, the <code>Closed<\/code> event does not get raised again. The rules for the Windows Runtime is that the <code>IClosable.<wbr \/>Close<\/code> method tells the object, &#8220;I have no further intention of using this object,&#8221; and further operations\u00b2 will fail with <code>RO_<wbr \/>E_<wbr \/>CLOSED<\/code>.<\/p>\n<p>The &#8220;did I already raise the <code>Closed<\/code> event?&#8221; flag is atomic because knowing that the reference count has dropped to 1 does not prove that only one thread can be using the object: A weak reference might increment the reference count back up, and then down to 1 a second time. C++\/WinRT and C++\/WRL objects support weak references by default, so this is something to worry about. If your framework doesn&#8217;t support weak references (or if you&#8217;ve disabled them), then the flag doesn&#8217;t need to be atomic because you know that there are no competing threads.<\/p>\n<p>\u00b9 Some people feel that C++ itself is also a disaster.<\/p>\n<p>\u00b2 With the exception of event handler unregistration and calling the <code>IClosable.<wbr \/>Close<\/code> itself.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, at least it&#8217;s possible.<\/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-109461","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Hey, at least it&#8217;s possible.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109461","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=109461"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109461\/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=109461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}