<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Aug 27, 2017, at 6:02 PM, Howard Lovatt via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">The async/await is very similar to the proposed Future (as I posed earlier) with regard to completion-handler code, they both re-write the imported completion-handler function using a closure, the relevant sentence from the Async Proposal is:<div class=""><br class=""></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px" class="">"Under the hood, the compiler rewrites this code using nested closures ..."<br class=""></blockquote><br class=""><div class="">Unlike the proposed future code the async code is not naturally parallel, in the running example the following lines from the async code are run in series, i.e. await blocks:</div><div class=""><br class=""></div><div class=""><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,&quot;Liberation Mono&quot;,Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)" class="">  <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> dataResource  <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> await <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="gmail-pl-pds" style="box-sizing:border-box">"</span>dataprofile.txt<span class="gmail-pl-pds" style="box-sizing:border-box">"</span></span>)
  <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageResource <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> await <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="gmail-pl-pds" style="box-sizing:border-box">"</span>imagedata.dat<span class="gmail-pl-pds" style="box-sizing:border-box">"</span></span>)
</pre></div><div class="">The equivalent lines using the proposed Future:</div><div class=""><pre style="box-sizing:border-box;font-family:SFMono-Regular,Consolas,&quot;Liberation Mono&quot;,Menlo,Courier,monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal;color:rgb(36,41,46)" class="">  <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> dataResource  <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="gmail-pl-pds" style="box-sizing:border-box">"</span>dataprofile.txt<span class="gmail-pl-pds" style="box-sizing:border-box">"</span></span>)
  <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">let</span> imageResource <span class="gmail-pl-k" style="box-sizing:border-box;color:rgb(215,58,73)">=</span> <span class="gmail-pl-c1" style="box-sizing:border-box;color:rgb(0,92,197)">loadWebResource</span>(<span class="gmail-pl-s" style="box-sizing:border-box;color:rgb(3,47,98)"><span class="gmail-pl-pds" style="box-sizing:border-box">"</span>imagedata.dat<span class="gmail-pl-pds" style="box-sizing:border-box">"</span></span>)
</pre></div><div class="">Run in parallel and therefore are potentially faster assuming that resources, like cores and IO, are available.</div><div class=""><br class=""></div><div class="">Therefore you would be better using a Future than an async, so why provide an async unless you can make a convincing argument that it allows you to write a better future?</div></div></div></blockquote><div><br class=""></div><div>On real systems going wide concurrently (and I will not call this parallelism on purpose, parallelism is about doing the same compute on different CPUs) is not often a win provided the thing you're doing is complex enough.</div><div>The reason for it is that most of these subsystems, and loadWebResource is a perfect example of this, use constrained resources that use locks and the like.</div><div><br class=""></div><div>In practice, you would really want all resources that you load from the internet to be handled from the same execution context (whether it's a dispatch queue, a thread or a CFRunloop is absolutely not relevant), because it's very likely that you'll end up contending concurrent executions of these loads through locks and the various shared resources in use (like your NIC and the networking stack).</div><div><br class=""></div><div>We've learned over the last 10 years of working on a massively concurrent system because of libdispatch making it too easy (some will say thanks to, but these aren't the one who need to cope with that it does to the OS :P), is that going wide by default is a design mistake and is very difficult to optimize when it goes bad.</div><div><br class=""></div><div>The right design is to have silos of execution contexts that are very few, as few as you can, and parallelize (and here I mean parallelize) the operations that benefit from using several compute units when you have proved that you do scale linearly (and scaling linearly is VERY hard, even for low values of NCPU as soon as what you do is complex enough)</div><div><br class=""></div><div>To me (but I'm catching up with the thread and maybe there have been refinements in that regard already), the loseness of the "execution context" that will run your completion handler here is a liability for the implementation of the runtime. Go for example is not doing that well, for the longest time the environment they recommended had a very small amount of physical threads because of scalability concerns around their goroutines scheduler. I'm mentioning go as an example of a language which is implementing CSP as a core concept, and has had (I'm not quite sure where they stand these days) quite a lot of trouble scaling the implementation.</div><div><br class=""></div><div><br class=""></div><div>IMSHO dispatch_get_global_queue() is in practice on of the worst thing that the dispatch API provides, because despite all the best efforts of the runtime, there aren't enough information at runtime about your operations/actors/... to understand what your intent is and optimize for it. Which means that the language should make sure that (1) the anti-pattern is not the default behavior and (2) the interface provides a way to give and propagate the hints (dependency relationships, ordering, execution context, priorities, ...) the runtime will potentially need upfront.</div><br class=""><blockquote type="cite" class=""><div class=""><div class="gmail_extra"><br clear="all" class=""><div class=""><div class="gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br class=""></div></div>
<br class=""><div class="gmail_quote">On 28 August 2017 at 09:59, Adam Kemp <span dir="ltr" class="">&lt;<a href="mailto:adam.kemp@apple.com" target="_blank" class="">adam.kemp@apple.com</a>&gt;</span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="">This example still has nested closures (to create a Future), and still relies on a synchronous get method that will block a thread. Async/await does not require blocking any threads.<div class=""><br class=""></div><div class="">I’m definitely a fan of futures, but this example isn’t even a good example of using futures. If you’re using a synchronous get method then you’re not using futures properly. They’re supposed to make it easy to avoid writing blocking code. This example just does the blocking call on some other thread.</div><div class=""><br class=""></div><div class="">Doing it properly would show the benefits of async/await because it would require more nesting and more complex error handling. By simplifying the code you’ve made a comparison between proper asynchronous code (with async/await) and improper asynchronous code (your example).</div><div class=""><br class=""></div><div class="">That tendency to want to just block a thread to make it easier is exactly why async/await is so valuable. You get simple code while still doing it correctly.&nbsp;</div><div class=""><br class=""><div id="m_-2707032511043914185AppleMailSignature" class="">--<div class="">Adam Kemp</div></div><div class=""><div class="h5"><div class=""><br class="">On Aug 27, 2017, at 4:00 PM, Howard Lovatt via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div class=""><div dir="auto" class="">The running example used in the white paper coded using a Future is:</div><div dir="auto" class=""><br class=""></div><div dir="auto" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">func processImageData1() -&gt; Future&lt;Image&gt; {</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; return AsynchronousFuture { _ -&gt; Image in</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; let dataResource &nbsp;= loadWebResource("dataprofile.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">t<wbr class="">xt") // dataResource and imageResource run in parallel.</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; let imageResource = loadWebResource("imagedata.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">dat<wbr class="">")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; let imageTmp &nbsp; &nbsp; &nbsp;= decodeImage(dataResource.get ?? Resource(path: "Default data resource or prompt user"), imageResource.get ?? Resource(path: "Default image resource or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; let imageResult &nbsp; = &nbsp;dewarpAndCleanupImage(</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">imageTm<wbr class="">p.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; &nbsp; &nbsp; return imageResult.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; }</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">}</span><br class=""></div><div dir="auto" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div dir="auto" class="">This also avoids the pyramid of doom; the pyramid is avoided by converting continuation-handlers into either a sync or future, i.e. it is the importer that eliminates the nesting by translating the code automatically.&nbsp;<br class=""></div><div dir="auto" class=""><br class=""></div><div dir="auto" class="">This example using Future also demonstrates three advantages of Future: they are naturally parallel (dataResource and imageResource lines run in parallel), they timeout automatically (get returns nil if the Future has taken too long), and if there is a failure (for any reason including timeout) it provides a method of either detecting the failure or providing a default (get returns nil on failure).&nbsp;</div><div dir="auto" class=""><br class=""></div><div dir="auto" class="">There are a three of other advantages a Future has that this example doesn’t show: control over which thread the Future runs on, Futures can be cancelled, and debugging information is available.</div><div dir="auto" class=""><br class=""></div><div dir="auto" class="">You could imagine `async` as a syntax sugar for Future, e.g. the above Future example could be:</div><div dir="auto" class=""><br class=""></div><div dir="auto" class=""><div dir="auto" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">func processImageData1() async -&gt; Image {</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; let dataResource &nbsp;= loadWebResource("dataprofile.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">t<wbr class="">xt") // dataResource and imageResource run in parallel.</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; let imageResource = loadWebResource("imagedata.</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">dat<wbr class="">")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; let imageTmp &nbsp; &nbsp; &nbsp;= decodeImage(dataResource.get ?? Resource(path: "Default data resource or prompt user"), imageResource.get ?? Resource(path: "Default image resource or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; let imageResult &nbsp; = &nbsp;dewarpAndCleanupImage(</span><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">imageTm<wbr class="">p.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user"))</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">&nbsp; &nbsp; return imageResult.get ?? Image(dataPath: "Default image or prompt user", imagePath: "Default image or prompt user")</span><br style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">}</span><br class=""></div><div dir="auto" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class=""><br class=""></span></div><div dir="auto" class="">Since an async is sugar for Future the async runs as soon as it is created (as soon as the underlying Future is created) and get returns an optional (also cancel and status would be still be present). Then if you want control over threads and timeout they could be arguments to async:</div><div dir="auto" class=""><br class=""></div><div dir="auto" class=""><span style="color:rgb(117,117,117);font-family:monospace,monospace;word-spacing:1px;background-color:rgb(255,255,255)" class="">func processImageData1() async(queue: DispatchQueue.main, timeout: .seconds(5)) -&gt; Image { ... }</span><br class=""></div></div><br class=""><div class="gmail_quote"><div class="">On Sat, 26 Aug 2017 at 11:00 pm, Florent Vilmart &lt;<a href="mailto:florent@flovilmart.com" target="_blank" class="">florent@flovilmart.com</a>&gt; wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



<div class="">
<div name="messageBodySection" class="">Howard, with async / await, the code is flat and you don’t have to unowned/weak self to prevent hideous cycles in the callbacks.<br class="">
Futures can’t do that</div></div><div class="">
<div name="messageReplySection" class=""><br class="">
On Aug 26, 2017, 04:37 -0400, Goffredo Marocchi via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt;, wrote:<br class="">
<blockquote type="cite" class="">With both he now built in promises in Node8 as well as libraries like Bluebird there was ample time to evaluate them and convert/auto convert at times libraries that loved callback pyramids of doom when the flow grows complex into promise based chains. Converting to Promises seems magical for the simple case, but can quickly descend in hard to follow flows and hard to debug errors when you move to non trivial multi path scenarios. JS is now solving it with their implementation of async/await, but the point is that without the full picture any single solution would break horribly in real life scenarios.<br class="">
<br class="">
<div id="m_-2707032511043914185m_-3623957891747021796AppleMailSignature" class="">Sent from my iPhone</div>
<div class=""><br class="">
On 26 Aug 2017, at 06:27, Howard Lovatt via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>&gt; wrote:<br class="">
<br class=""></div>
<blockquote type="cite" class="">
<div class="">
<div class="">My argument goes like this:
<div class=""><br class="">
<div class="">&nbsp; 1. You don't need async/await to write a powerful future type; you can use the underlying threads just as well, i.e. future with async/await is no better than future without.&nbsp;</div>
<div class=""><br class=""></div>
<div class="">&nbsp; 2. Since future is more powerful, thread control, cancel, and timeout, people should be encouraged to use this; instead because async/await are language features they will be presumed, incorrectly, to be the best way, consequently people will get into trouble with deadlocks because they don't have control.</div>
</div>
<div class=""><br class=""></div>
<div class="">&nbsp; 3. async/await will require some engineering work and will at best make a mild syntax improvement and at worst lead to deadlocks, therefore they just don't carry their weight in terms of useful additions to Swift.</div>
<div class=""><br class=""></div>
<div class="">Therefore, save some engineering effort and just provide a future library.</div>
<div class=""><br class=""></div>
<div class="">To turn the question round another way, in two forms:</div>
<div class=""><br class=""></div>
<div class="">&nbsp; 1. What can async/wait do that a future can't?</div>
<div class=""><br class=""></div>
<div class="">&nbsp; 2. How will future be improved if async/await is added?</div>
<div class=""><br class=""></div>
</div>
<div class="gmail_extra"><br clear="all" class="">
<div class="">
<div class="m_-2707032511043914185m_-3623957891747021796gmail_signature" data-smartmail="gmail_signature">&nbsp; -- Howard.<br class=""></div>
</div>
<br class="">
<div class="gmail_quote">On 26 August 2017 at 02:23, Joe Groff <span class="">&lt;<a href="mailto:jgroff@apple.com" target="_blank" class="">jgroff@apple.com</a>&gt;</span> wrote:<br class="">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word" class="">
<div class=""><br class="">
<div class="">
<blockquote type="cite" class="">
<div class="">On Aug 25, 2017, at 12:34 AM, Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" target="_blank" class="">howard.lovatt@gmail.com</a>&gt; wrote:</div>
<br class="m_-2707032511043914185m_-3623957891747021796m_1547456930512826529Apple-interchange-newline">
<div class=""><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline!important" class=""><span class="m_-2707032511043914185m_-3623957891747021796m_1547456930512826529Apple-converted-space">&nbsp;</span>In particular a future that is cancellable is more powerful that the proposed async/await.</span></div>
</blockquote>
</div>
<br class=""></div>
<div class="">It's not more powerful; the features are to some degree disjoint. You can build a Future abstraction and then use async/await to sugar code that threads computation through futures. Getting back to Jakob's example, someone (maybe the Clang importer, maybe Apple's framework developers in an overlay) will still need to build infrastructure on top of IBActions and other currently ad-hoc signalling mechanisms to integrate them into a more expressive coordination framework.</div>
<div class="m_-2707032511043914185m_-3623957891747021796HOEnZb"><font color="#888888" class=""></font>
<div class=""><font color="#888888" class=""><br class=""></font></div>
<div class=""><font color="#888888" class="">-Joe</font></div>
</div>
</div>
</blockquote>
</div>
<br class=""></div>
</div>
</blockquote>
<blockquote type="cite" class="">
<div class=""><span class="">______________________________<wbr class="">_________________</span><br class="">
<span class="">swift-evolution mailing list</span><br class="">
<span class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a></span><br class="">
<span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a></span><br class=""></div>
</blockquote>
</blockquote>
</div>
</div></blockquote></div></div><div dir="ltr" class="">-- <br class=""></div><div class="m_-2707032511043914185gmail_signature" data-smartmail="gmail_signature">-- Howard.</div>
</div></blockquote><blockquote type="cite" class=""><div class=""><span class="">______________________________<wbr class="">_________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a></span><br class=""></div></blockquote></div></div></div></div></blockquote></div><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>