{"id":105828,"date":"2021-10-25T07:00:00","date_gmt":"2021-10-25T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105828"},"modified":"2021-10-25T08:33:42","modified_gmt":"2021-10-25T15:33:42","slug":"20211025-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20211025-00\/?p=105828","title":{"rendered":"A very brief introduction to patterns for implementing a COM object that hands out references to itself"},"content":{"rendered":"<p>A common scenario for a COM object is that it needs to register itself as a callback or otherwise hand out references to itself. There are a few patterns for this.<\/p>\n<p>One of the first things you have to decide is whether the reference to the main object should be strong (keep the main object alive) or weak (not be considered for deciding whether the main object should be kept alive).<\/p>\n<p>Let&#8217;s look at the weak pattern first.<\/p>\n<p>If you don&#8217;t want the callback registration to keep the object alive, then you typically give the callback object a weak reference to the main object. When the callback object is invoked, it converts the weak reference to a strong reference and calls the main object. Since the reference is weak, the existence of the callback object has no effect on the lifetime of the main object.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Callback<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">ICallback<\/td>\n<td>\u2190<\/td>\n<td>event source<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Widget<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; border-bottom: none;\" colspan=\"2\">refcount<\/td>\n<\/tr>\n<tr>\n<td>client<\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px black;\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">IWidget<\/td>\n<td>\u2190<\/td>\n<td style=\"border: solid 1px black; border-top: none;\" colspan=\"2\">weak reference<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">refcount<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\" rowspan=\"4\">state data<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>In this model, the only reference counts on the main Widget object come from the client. When the client releases their last reference, the main Widget destructs, and the main Widget object unregisters the callback from the event source, thereby causing the Callback object to destruct as well.<\/p>\n<p>Another pattern is to factor the <i>state data<\/i> into a shared object:<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Widget<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Callback<\/td>\n<\/tr>\n<tr>\n<td>client<\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px black;\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">IWidget<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">ICallback<\/td>\n<td>\u2190<\/td>\n<td>event source<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; border-bottom: none;\" colspan=\"2\">refcount<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; border-bottom: none;\" colspan=\"2\">refcount<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; border-top: none;\" colspan=\"2\">shared_ptr<\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px black; width: 19ex;\" rowspan=\"4\">state data<\/td>\n<td>\u2190<\/td>\n<td style=\"border: solid 1px black; border-top: none;\" colspan=\"2\">some_ptr<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If the <code>some_ptr<\/code> is a weak reference, then we have the same pattern as before. But if you make it a <code>shared_ptr<\/code>, then the callback will keep the state alive. This might be useful if the Callback is used to signal the completion of some sort of activity, and you need to keep the state data alive until the activity is complete, but you might want the destruction of the Widget to issue a Cancel request to the event source to accelerate the completion of the activity.<\/p>\n<p>In the strong pattern, the callback registration keeps the main object alive. The usual way of doing this is to just upgrade our first diagram to use a strong reference from the Callback object to the main object.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Callback<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td colspan=\"2\">\u00a0<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">ICallback<\/td>\n<td>\u2190<\/td>\n<td>event source<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Widget<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; border-bottom: none;\" colspan=\"2\">refcount<\/td>\n<\/tr>\n<tr>\n<td>client<\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px black;\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">IWidget<\/td>\n<td>\u2190<\/td>\n<td style=\"border: solid 1px black; border-top: none;\" colspan=\"2\"><span style=\"color: blue; background-color: #fdfd96;\">strong<\/span> reference<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">refcount<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\" rowspan=\"4\">state data<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You might then realize that there&#8217;s no point creating a separate callback object: The main object can be its own callback.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"0\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">Widget<\/td>\n<\/tr>\n<tr>\n<td>client<\/td>\n<td>\u2192<\/td>\n<td style=\"border: solid 1px black;\" rowspan=\"2\" valign=\"baseline\">IUnknown<\/td>\n<td style=\"border: solid 1px black;\">IWidget<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\">ICallback<\/td>\n<td>\u2190<\/td>\n<td>event source<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\">refcount<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black;\" colspan=\"2\" rowspan=\"4\">state data<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This is a very common pattern, but it does introduce a few problems compared to the separate-callback-object pattern.<\/p>\n<p>One problem is that the client can <code>Query\u00adInterface<\/code> for <code>ICallback<\/code> and use that to manipulate the Widget in ways that weren&#8217;t intended, since it can invoke the callback from the client and feed it fake data. (Conversely, the event source can <code>Query\u00adObject<\/code> for <code>IWidget<\/code>, but that is unlikely to occur in practice, since the event source doesn&#8217;t care about widgets.) With the separate callback, the <code>QueryInterface<\/code> method main object responds only to <code>IWidget<\/code>, and the <code>QueryInterface<\/code> method callback object responds only to <code>ICallback<\/code>. The client has no way to access the callback object, and the event source has no way to access the main object.<\/p>\n<p>A second problem is if the main object needs to register for multiple event sources, all of which use the same <code>ICallback<\/code> interface. There is only one <code>ICallback<\/code> in the main object, so it has no choice but to pass the same <code>ICallback<\/code> to both event sources, even though we may want the two callbacks to do different things. Again, the separate callback object avoids this problem because each callback object can do something different when it is called.<\/p>\n<p>But there&#8217;s still a solution to this problem without having to go back to the separate callback objects. We&#8217;ll look at this trick next time, and fleshing out the idea will give us a tour through a lot of C++ features, so it might be interesting even if you don&#8217;t care about COM.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;ll look at many choices, but focus on one.<\/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-105828","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>We&#8217;ll look at many choices, but focus on one.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105828","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=105828"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105828\/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=105828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}