{"id":391,"date":"2008-09-27T10:17:32","date_gmt":"2008-09-26T22:17:32","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=391"},"modified":"2008-09-27T10:17:32","modified_gmt":"2008-09-26T22:17:32","slug":"free-yourself","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/391\/","title":{"rendered":"Free Yourself"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>Barry Kelly recently posted <a href=\"http:\/\/barrkel.blogspot.com\/2008\/09\/smart-pointers-in-delphi.html\" target=\"_blank\">an example of &#8220;smart&#8221; pointers<\/a> (specifically the auto-pointer variant of a smart pointer) using generics in Delphi 2009.\u00a0 It was an interesting use of generics but the end result was something that has &#8211; in part at least &#8211; been possible for some time in Delphi even without generics &#8211; reliable cleanup of objects.<\/p>\n<p>This was something that a colleague of mine, Geza Sabo, pointed out, based on some code I&#8217;d previously shared with him to robustly manage the hourglass cursor in a GUI application.<\/p>\n<p><!--more--><\/p>\n<p>Barry&#8217;s &#8211; and others &#8211; generics based approach aims (I think) to provide a generally useful mechanism for declaring some object reference that will automatically be free&#8217;d when it goes out of scope or is part of a container that itself is disposed of, for example in class member variable (field) declarations.<\/p>\n<p>In practice I think &#8211; day-to-day &#8211; that the most useful effect of smart pointers will be the removal of the boiler-plate code that is otherwise needed to ensure correct clean-up of temporary objects in method implementations:<\/p>\n<pre class=\"delphi\">  var\r\n    list: TStringList;\r\n  begin\r\n    list := TStringList.Create;\r\n    try\r\n      \/\/ Do work with list\r\n    finally\r\n      FreeAndNIL(list);\r\n    end;\r\n  end;<\/pre>\n<p>This boiler-plate can become particularly unattractive when multiple temporary objects are involved.  With the generics solution presented by Barry, the need for the boiler-plate is entirely removed:<\/p>\n<pre class=\"delphi\">  var\r\n    list: TSmartPointer&lt;TStringList&gt;;\r\n  begin\r\n    list := TStringList.Create;\r\n    \/\/ Do work with list\r\n  end;<\/pre>\n<p>Unfortunately there are some problems with the implementation (mostly problems with side effects of the debugger) <a href=\"http:\/\/barrkel.blogspot.com\/2008\/09\/smart-pointers-in-delphi.html\" target=\"_blank\">discussed in the comments of Barry&#8217;s post<\/a>.<\/p>\n<p>The biggest problem (for me) is that it only works in Delphi 2009, but for the temporary objects case at least, there is an alternative that will work even in older Delphi versions.\u00a0 I personally am also uncomfortable with expressing behaviour in a declaration, but that is a foible of mine that others may not necessarily share.<\/p>\n<h2>How It Works<\/h2>\n<p>The underlying mechanism that makes the generics approach possible is referencing counting on an interfaced object, a mechanism which of course is not itself dependent on generics at all and we can use the exact same mechanism:<\/p>\n<pre class=\"delphi\">interface\r\n\r\n  type\r\n    PObject = ^TObject;\r\n\r\n  function AutoFree(const aObject: PObject): IUnknown;\r\n\r\nimplementation\r\n\r\n  uses\r\n    SysUtils;\r\n\r\n  type\r\n    TAutoFree = class(TInterfacedObject, IUnknown)\r\n    private\r\n      fObject: PObject;\r\n    public\r\n      constructor Create(const aObject: PObject);\r\n      destructor Destroy; override;\r\n    end;\r\n\r\n  constructor TAutoFree.Create(const aObject: PObject);\r\n  begin\r\n    inherited Create;\r\n    fObject := aObject;\r\n  end;\r\n\r\n  destructor TAutoFree.Destroy;\r\n  begin\r\n    FreeAndNIL(fObject^);\r\n    inherited;\r\n  end;\r\n\r\n  { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }\r\n  function AutoFree(const aObject: PObject): IUnknown;\r\n  begin\r\n    result := TAutoFree.Create(aObject);\r\n  end;<\/pre>\n<p>In use, this implementation is very similar to the generics based approach (for temporary objects):<\/p>\n<pre class=\"delphi\">  var\r\n    list: TStringList;\r\n  begin\r\n    list := TStringList.Create;\r\n    AutoFree(@list);\r\n    \/\/ Do work with list\r\n  end;<\/pre>\n<p>There are three fairly obvious differences and one perhaps not so obvious:<\/p>\n<p style=\"padding-left: 30px;\">1. The variable is declared as what it is, not as how it should behave<\/p>\n<p style=\"padding-left: 30px;\">2. There is still some boiler-plate (the call to <strong>AutoFree()<\/strong>)<\/p>\n<p style=\"padding-left: 30px;\">3. The use of the @ operator<\/p>\n<p>The first difference is important from a usage and maintenance point of view.<\/p>\n<p>In terms of usage we continue to use our variables as what they are; wrapping them inside a smart pointer makes this more cumbersome in some cases.<\/p>\n<p>From a maintenance point of view it allows us to change the behaviour of our code (in cases where the changes would not otherwise affect the variables required) without having to change variable declarations.\u00a0 It also means that changes to behaviour (in terms of changes to the body of our methods) cannot inadvertently break the behaviour established in the declaration (which in practice may be some distance removed from the behavioural code being modified).<\/p>\n<p>The second difference actually follows from the first.\u00a0 Since behaviour is not now introduced in the declaration it is now necessary to specify that behaviour in the code.\u00a0 However, the impact on that code is still far less obtrusive than the usual <strong>try..finally<\/strong> boiler-plate.\u00a0 It is also more flexible, thanks to the third and final (obvious) difference.<\/p>\n<p>This third difference is the use of the the <strong>@<\/strong> operator in the calls to <strong>AutoFree()<\/strong>.\u00a0 Initially this might appear cumbersome &#8211; why not just pass the object reference to be free&#8217;d directly?\u00a0 The answer to that brings me to the perhaps not-so-obvious difference.<\/p>\n<p>By using references to object references, where we specify the behaviour is not actually important.\u00a0 It also means that the behaviour is robust where the objects involved are perhaps only conditionally created and\/or sometimes also explicitly free&#8217;d:<\/p>\n<pre class=\"delphi\">  var\r\n    listA: TStringList;\r\n    listB: TStringList;\r\n  begin\r\n    AutoFree(@listA);\r\n    AutoFree(@listB);\r\n\r\n    listA := TStringList.Create;\r\n    listB := NIL;\r\n\r\n    \/\/ We do some work with listA\r\n\r\n    if someCondition then\r\n    begin\r\n      listB := TStringList.Create;\r\n\r\n      \/\/ Do work involving listB (and maybe listA too)\r\n   \u00a0end;\r\n  end;<\/pre>\n<p>In the behavioural aspect of our code (the method body) we stipulate &#8211; via a call to <strong>AutoFree()<\/strong> &#8211; that when we exit the method, any reference in the specified variable should be freed.  It doesn&#8217;t actually matter at the point at which we make that call whether that variable is currently <strong>NIL<\/strong>, uninitialised<strong>(*)<\/strong> or already contains a valid object reference.  What will matter is what that reference contains when the method exits<strong>(**)<\/strong>.<\/p>\n<p><em><strong>(*) <\/strong>it <\/em><em><span style=\"text-decoration: underline;\">will<\/span> matter if the variable <\/em><em>is <span style=\"text-decoration: underline;\">never<\/span> initialised (see problem #2, below).<\/em><\/p>\n<p><em><strong>(**)<\/strong> even if the method raises an exception the <strong>AutoFree()<\/strong> references will still be reliably cleaned-up.<\/em><\/p>\n<p>Of course, this approach itself isn&#8217;t perfect.<\/p>\n<p style=\"padding-left: 30px;\">1. As previously mentioned, <strong>AutoFree()<\/strong> deals specifically with temporary objects and does not address more general uses of &#8220;smart&#8221; pointers.<\/p>\n<p style=\"padding-left: 30px;\">2. Unfortunately for a reason I can&#8217;t quite fathom, a call to <strong>AutoFree(@ref)<\/strong> seems to be sufficient for the compiler to consider <strong>ref<\/strong> to be initialised, so you will <span style=\"text-decoration: underline;\">not<\/span> get a <strong>&#8220;Variable &#8216;ref&#8217; might not have been initialized&#8221;<\/strong> warning if you call <strong>AutoRef()<\/strong> for some variable but then neglect to initialise that variable.<\/p>\n<p style=\"padding-left: 30px;\">3. An interfaced object is a lot of overhead for each reference being <strong>AutoFree()<\/strong>d &#8211; of course this can easily be addressed by an overload to accept an array of <strong>PObject<\/strong> references and extending the <strong>TAutoFree<\/strong> class to manage more than one reference per instance.<\/p>\n<p style=\"padding-left: 30px;\">\n<h2>Hourglass Management<\/h2>\n<p>As I mentioned at the start, the initial implementation of <strong>AutoFree()<\/strong> was inspired by a more specific implementation that utilised the same reference counting mechanism to reliably manage the hourglass cursor in GUI applications.<\/p>\n<p>But I&#8217;m saving that for next time.<\/p>\n<p>\ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">4<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> Barry Kelly recently posted an example of &#8220;smart&#8221; pointers (specifically the auto-pointer variant of a smart pointer) using generics in Delphi 2009.\u00a0 It was an interesting use of generics but the end result was something that has &#8211; in part at least &#8211; been possible for some time in Delphi even without generics &#8211; reliable [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":[]},"categories":[4],"tags":[292],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-6j","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":338,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/338\/","url_meta":{"origin":391,"position":0},"title":"Delphi 2009 &#8211; A Heads-Up for Low-Level Coders","date":"13 Sep 2008","format":false,"excerpt":"Prompted by a conversation with some colleagues where-in we collectively speculated about the implementation details of a generic class and what impact - if any - this might have on performance vs a \"traditional\" polymorphic equivalent, I threw together a quick performance test case in my Smoketest framework, and as\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":180,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/180\/","url_meta":{"origin":391,"position":1},"title":"Latest Tibur\u00f3n Preview","date":"14 Aug 2008","format":false,"excerpt":"I was a little disappointed that the preview webinar this morning was little more than a re-run of the same content from a little over a week ago, albeit with some downloadable PowerPoint slides this time. It was at least an opportunity for some more Q&A and a couple of\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":876,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/876\/","url_meta":{"origin":391,"position":2},"title":"Commonest Weakness&#8230;","date":"06 Jun 2012","format":false,"excerpt":"Stefan Glienke recently added his contribution to the various solutions for implementing weak interface references in Delphi. He quite neatly and comprehensively covers the need for such things, but his approach requires generics support and so is limited to later versions of the compiler (just how late really depends on\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":134,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/134\/","url_meta":{"origin":391,"position":3},"title":"A New Poll","date":"08 Aug 2008","format":false,"excerpt":"My first poll looked ahead to the next version of Delphi, asking what we were looking forward to.\u00a0 It came as no real surprise to find Generics and Unicode leading the pack. So I thought I'd turn the perspective around to look in the opposite direction and find out where\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":28,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/28\/","url_meta":{"origin":391,"position":4},"title":"Tiburon Preview","date":"02 Aug 2008","format":false,"excerpt":"A roundup of that part of the Preview I saw of Tiburon - the next release of Delphi from CodeGear.","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":700,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/700\/","url_meta":{"origin":391,"position":5},"title":"The case for case[]","date":"30 Nov 2010","format":false,"excerpt":"Eric Grange (resurrector of the increasingly interesting looking DWS project) recently posted about a new idea he has had for the DWS engine, which in turn gave me an idea, or rather, prompted me to come up with what I think may be a new spin on an old one.\u2026","rel":"","context":"In &quot;Delphi&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/391"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=391"}],"version-history":[{"count":11,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/391\/revisions"}],"predecessor-version":[{"id":402,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/391\/revisions\/402"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}