{"id":1684,"date":"2014-11-28T14:42:16","date_gmt":"2014-11-28T04:42:16","guid":{"rendered":"http:\/\/www.malcolmgroves.com\/blog\/?p=1684"},"modified":"2014-12-03T10:59:41","modified_gmt":"2014-12-03T00:59:41","slug":"wtf-is-a-future","status":"publish","type":"post","link":"http:\/\/www.malcolmgroves.com\/blog\/?p=1684","title":{"rendered":"WTF is a Future?"},"content":{"rendered":"<p>Of the abstractions introduced in the Parallel Programming Library, the IFuture&lt;T&gt; seems to be the one that many people have difficulty understanding.<\/p>\n<p>Both TTask and TParallel.For seem reasonably easy to understand conceptually, even if you don&#8217;t understand all the details. TTask is about some code you want to run in parallel to the main thread. TParallel.For is about performing some actions on the items in a collection in parallel. In both cases you are focussed on the actions you want to perform.<!--more--><\/p>\n<p>I&#8217;ve struck many people however, who struggle to conceptually understand a Future, and when I drill into why, in most cases it&#8217;s because they are thinking about Futures in the same way: as being about some code or actions they want to perform. I&#8217;ve even had someone say to me &#8220;This is about some job I want to have happen in the future, but not now? I don&#8217;t get it.&#8221;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1693\" src=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/11\/nofuture-e1350930184618.jpeg\" alt=\"nofuture-e1350930184618\" width=\"400\" height=\"220\" srcset=\"http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/11\/nofuture-e1350930184618.jpeg 400w, http:\/\/www.malcolmgroves.com\/blog\/wp-content\/uploads\/2014\/11\/nofuture-e1350930184618-300x165.jpeg 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<p>If you&#8217;re in this situation, stop thinking about Futures in the context of the activities you want to do.<\/p>\n<blockquote><p>A Future is not about a task you want to perform in the future, it&#8217;s about a value you know you&#8217;ll want in the future.<\/p><\/blockquote>\n<p>Let&#8217;s say I&#8217;m trying to make a decision about whether I can process a customer order:<\/p>\n<pre>procedure TFormThreading.OrderItem(const CustomerID,  ItemID: String; OrderQty: Integer);\r\nvar\r\n  StockLevel : Integer;\r\n  PaidTheirBills : Boolean;\r\nbegin\r\n  StockLevel := GetStockLevel(ItemID); \/\/ very slow\r\n  PaidTheirBills := HaveTheyPaid(CustomerID); \/\/ also very slow\r\n\r\n  if (StockLevel &gt;= OrderQty) and (PaidTheirBills) then\r\n    \/\/ process the order\r\nend;<\/pre>\n<p>In this scenario, there might be several pieces of information I need before I can go ahead and process the order, such as whether we have enough stock, whether the customer has good enough credit, and potentially others.<\/p>\n<p>Further, let&#8217;s assume that the calls to find out our stock levels and also the customer&#8217;s credit worthiness are time consuming calls. I could do them sequentially, as above, but then every order will take a long time.<\/p>\n<p>Yes, I could rejig the logic and check the StockLevel straight after retrieving it, exiting if we don&#8217;t have enough, but that will still leave me with a slow process in the cases where we do.<\/p>\n<p>But if we step back, we know we need two values to make the decision: StockLevel and PaidTheirBills. Further, the decision will be made in the future, we first have to retrieve the values. So, let&#8217;s use a Future.<\/p>\n<p>Let&#8217;s rejig the code to look like this:<\/p>\n<pre class=\"\">procedure TFormThreading.OrderItem(const CustomerID, ItemID: String; OrderQty: Integer);\r\nvar\r\n  StockLevel : IFuture&lt;Integer&gt;;\r\n  PaidTheirBills : Boolean;\r\nbegin\r\n  StockLevel := TTask.Future(function : Integer\r\n                             begin\r\n                               \/\/ very slow\r\n                               Result := GetStockLevel(ItemID);\r\n                             end);\r\n  PaidTheirBills := HaveTheyPaid(CustomerID); \/\/ also very slow\r\n\r\n  if (StockLevel.Value &gt;= OrderQty) and (PaidTheirBills) then\r\n    \/\/ process the order\r\nend;<\/pre>\n<p>Instead of being an Integer, StockLevel is now an IFuture&lt;Integer&gt;. \u00a0It&#8217;s not an Integer we need right now, but one we need in the future. We instantiate it by calling TTask.Future, passing in an anonymous method which contains the code needed to calculate its value. This will start running in the background, but in the meantime, we&#8217;ll continue on to calculate the other value we need, PaidTheirBills, another time consuming call.<\/p>\n<p>When it comes time to make our decision, a couple of things\u00a0might have happened.<\/p>\n<ul>\n<li>Our anonymous method might have already finished running, in which case calling StockLevel.Value will immediately return the result, which we can then compare to OrderQty.<\/li>\n<li>Our anonymous method might still be running, in which case the call to StockLevel.Value will block until it finishes.<\/li>\n<\/ul>\n<p>But either way, we know that both values will be calculated and compared before we process the order, but it&#8217;s likely the user will not have waited as long for the result.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Of the abstractions introduced in the Parallel Programming Library, the IFuture&lt;T&gt; seems to be the one that many people have difficulty understanding. Both TTask and TParallel.For seem reasonably easy to understand conceptually, even if you don&#8217;t understand all the details. TTask is about some code you want to run in parallel to the main thread. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[98,123],"tags":[48],"class_list":["post-1684","post","type-post","status-publish","format-standard","hentry","category-coding","category-parallel","tag-embarcadero"],"_links":{"self":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1684","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1684"}],"version-history":[{"count":11,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1684\/revisions"}],"predecessor-version":[{"id":1712,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1684\/revisions\/1712"}],"wp:attachment":[{"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1684"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1684"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.malcolmgroves.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1684"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}