<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=""><br class=""><div class="">
-Pierre

</div>
<div><br class=""><blockquote type="cite" class=""><div class="">On Sep 26, 2017, at 1:57 PM, Jean-Daniel &lt;<a href="mailto:mailing@xenonium.com" class="">mailing@xenonium.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;" class=""><br class="Apple-interchange-newline"><br class=""><blockquote type="cite" class=""><div class="">Le 26 sept. 2017 à 22:38, Pierre Habouzit &lt;<a href="mailto:phabouzit@apple.com" class="">phabouzit@apple.com</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class=""><div class="" 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; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class=""><div class="">On Sep 26, 2017, at 11:22 AM, Jean-Daniel via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><div class=""><br class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;"><blockquote type="cite" class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;">Le 26 sept. 2017 à 00:13, Adam Kemp &lt;<a href="mailto:adam_kemp@apple.com" class="">adam_kemp@apple.com</a>&gt; a écrit :<br class=""><br class=""><blockquote type="cite" class="">On Sep 25, 2017, at 3:04 PM, Jean-Daniel via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class="">Le 25 sept. 2017 à 21:42, John McCall via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :<br class=""><br class="">This doesn't have to be the case, actually. &nbsp;The intrinsics as Chris described them wouldn't be sufficient, but you could require a "current queue" to be provided when kicking off an async function from scratch, as well as any other "async-local" context information you wanted (e.g. QoS and the other things that Dispatch tracks with attributes/flags that are generally supposed to persist across an entire async operation).<br class=""><br class=""></blockquote><br class="">My response was about the ‘implicitly’ part. I hope we will get a rich API that let us specify return queue, QoS and more, but how do you plan to fulfill the « current queue » requirement implicitly ?<br class=""></blockquote><br class="">My earlier response to this thread both linked to a previous thread about this and explained how C# does it. It will require some library support, but it can be done, and IMO should be done. As I’ve stressed repeatedly, async/await without this behavior will be very difficult to use correctly. I really hope we don’t settle for that.<br class=""></blockquote><br class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;"><span class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">In C#, the model is far simple as there is not concept of a single dispatch queue that can execute work on any thread. You can easily use TLS to store a default context. Each UI thread can have a context that dispatch completion on the message queue, but AFAIK,</span></div></blockquote><div class=""><br class=""></div><br class=""><blockquote type="cite" class=""><div class=""><span class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">there is not DispatchQueue Local Storage yet.</span></div></blockquote><div class=""><br class=""></div><div class="">There is, see dispatch_queue*_specific()</div><br class=""><blockquote type="cite" class=""><div class=""><span class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">Even something as simple as getting the current queue is not reliable (see dispatch_get_current_queue man page for details).</span><br class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;"></div></blockquote><div class=""><br class=""></div><div class="">This is a sharp construct for clients, but not for the runtime / compiler that can be taught how not to fall in the traps of this API.</div><div class=""><br class=""></div><div class="">Just to debunk myths, dispatch_get_current_queue() is VERY WELL defined, but has two major issues: nesting &amp; refcounting.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><b class="">Nesting</b></div></div><blockquote class="" 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; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><br class=""></div><div class="">Nesting refers to the fact that when you call code that takes a queue and a callback, you may observe *another* queue:</div></div><div class=""><div class=""><br class=""></div></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class="">run_something_and_call_me_back(arg1, arg2, on_queue, ^{</div></div></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><b class="">&nbsp; &nbsp; assert(dispatch_get_current_queue() == on_queue); // may crash</b></div></div></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class="">&nbsp; &nbsp; ... my stuff ...</div></div></blockquote><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class="">});</div></div></blockquote><br class=""></blockquote><blockquote class="" 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; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;">The reason is that run_something_and_call_me_back() may create a queue that targets `on_queue` and then this private queue is what is returned which is both unexpected and exposing internals of the implementation of run_something_and_call_me_back() which is all wrong.</blockquote><blockquote class="" 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; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><br class=""></blockquote><blockquote class="" 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; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;">A corollary is that people attempting to implement recursive locking (which is a bad idea in general anyway) with dispatch_get_current_queue() will fail miserably.</blockquote><div class="" 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; -webkit-text-stroke-width: 0px;"><br class=""></div><b class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Refcounting</b><div class="" 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; -webkit-text-stroke-width: 0px;"><br class=""></div><blockquote class="" 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; -webkit-text-stroke-width: 0px; margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class="">Because dispatch has a notion of internal refcount, in ARC world, this will crash most of the time:</div></div><div class=""><br class=""></div><div class="">dispatch_async(dispatch_queue_create_with_target("foo", NULL, NULL), ^{</div><div class="">&nbsp; &nbsp;<span class="Apple-converted-space">&nbsp;</span><b class="">__strong</b><span class="Apple-converted-space">&nbsp;</span>dispatch_queue cq = dispatch_get_current_queue();<span class="Apple-converted-space">&nbsp;</span><b class="">// will usually crash with a resurrection error</b></div><div class="">});</div></blockquote><div class="" 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; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" 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; -webkit-text-stroke-width: 0px;"><br class=""></div><span class="" 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; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">These two edges is why we deprecated this interface for humans.</span><div class="" 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; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" 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; -webkit-text-stroke-width: 0px;">1) A compiler though is not affected by the first issue because the context it would capture would have to not be programatically accessible to clients</div><div class="" 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; -webkit-text-stroke-width: 0px;">2) The Swift runtime can know to take "internal" refcounts when capturing this hidden pointer and is not affected by the second problem either.<br class=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">tl;dr: what is badly defined is allowing clients to get a pointer to the current queue with a real +1, but that is WAY stronger than what the language runtime needs.</div><div class=""><br class=""></div><br class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><span class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px; float: none; display: inline !important;">That’s why I’m saying it will be difficult to define a reasonable default context that can be used implicitly.</span><br class="" style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;"></div></blockquote><br class=""></div><div class="">This is just not true. This is both easy and reasonable.</div><br class=""></div></div></div></blockquote><br class="">I’m glade to be wrong about that point ;-)</div><div style="font-family: SFMono-Light; font-size: 11px; 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; -webkit-text-stroke-width: 0px;" class="">One issue I still see is what should be the default when running on a bare pthread outside of any queue context. Or is there a queue associated with any thread ?</div></div></blockquote><br class=""></div><div>My thinking is that we need to have a notion of "current place to run swift bullshi^Wclosures".</div><div>It could be the current queue if there's one, or the current CFRunLoop (if there's one already made)</div><div>It could be the current "libfoobar event loop", ...</div><div><br class=""></div><div>and if there's neither, then I think it would be completely appropriate to crash at runtime because it means you made a thread without the Swift runtime knowledge without any setup to allow running swift actors/asyncs/... on it and then called into Swift code that needs it.</div><div><br class=""></div><div>In less joking tones, what I was thinking about is that the runtime should be able to have a way to get to the "current actor/async/.... context" for a thread which is an object that implements a given protocol that has the necessary methods to receive asyncs/actors/...</div><div><br class=""></div><div>I hope I'm making sense.</div><div><br class=""></div><div>-Pierre</div><br class=""></body></html>