<div>Hi Ole,</div><div><br></div><div>A quick follow-up--are you suggesting calling withExtendedLifetime inside the closure passed to async, as below?</div><div><br></div><div><div>class AsyncHandle {</div><div><br></div><div>    let handle: Handle</div><div><br></div><div>    deinit {</div><div>        let handle: Handle = self.handle</div><div>        q.async {</div><div>            withExtendedLifetime(handle) {}</div><div>        }</div><div>    }</div><div>}</div></div><div><br></div><div>If so, it seems that that may be a final answer to (3).  It does raise an additional question, however:</div><div><br></div><div>(6) Would we expect calling withExtendedLifetime to have different behavior from calling an @inline(never) function from a closure enqueued async from deinit?</div><div><br></div><div>Thank you again,</div><div>Nate Chandler</div><div><br><div class="gmail_quote"><div>On Mon, Feb 27, 2017 at 1:20 PM Nate Chandler &lt;<a href="mailto:nathaniel.chandler@gmail.com">nathaniel.chandler@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_msg">Hi Ole,</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Thank you very much for your response.  </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I don&#39;t believe withExtendedLifetime can help out here.  The trouble is that withExtendedLifetime only extends a lifetime until the end of a scope, synchronously.  </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In my case, I want to extend the lifetime of Handle from AsyncHandle&#39;s deinit until a closure enqueued asynchronously (from AsyncHandle&#39;s deinit) is invoked.  Using withExtendedLifetime, I could only extend the lifetime of Handle until the end of AsyncHandle&#39;s deinit method.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I want to write</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">class AsyncHandle {</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">    let handle: Handle</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">    deinit {</div><div class="gmail_msg">        let handle: Handle = self.handle</div><div class="gmail_msg">        q.async {</div><div class="gmail_msg">            letHandleDieNow(handle)</div><div class="gmail_msg">        }</div><div class="gmail_msg">    }</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">}</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">If I tried to use withExtendedLifetime, I could only write</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg">class AsyncHandle {</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">    let handle: Handle</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">    deinit {</div><div class="gmail_msg">        let handle: Handle = self.handle</div><div class="gmail_msg">        withExtendedLifetime(handle) { handle in</div><div class="gmail_msg">            q.async {</div><div class="gmail_msg">                // This is where I want handle to finally be deinitialized</div><div class="gmail_msg">            }</div><div class="gmail_msg">        }</div><div class="gmail_msg">        // This is where handle is actually deinitialized, prior (probably) to the invocation of the closure passed to async</div><div class="gmail_msg">    }</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">}</div></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Please let me know if I am misunderstanding your suggestion or the withExtendedLifetime API.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Thank you very much,</div><div class="gmail_msg">Nate Chandler</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">On Mon, Feb 27, 2017 at 12:31 PM Ole Begemann &lt;<a href="mailto:ole@oleb.net" class="gmail_msg" target="_blank">ole@oleb.net</a>&gt; wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On 27/02/2017 15:17, Nate Chandler via swift-users wrote:<br class="gmail_msg">
&gt; Hello all,<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; I&#39;m encountering a behavior around object lifetime and deinitialization<br class="gmail_msg">
&gt; that is surprising to me.  Here&#39;s an approximation of what I&#39;m encountering:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; I have a class Handle whose deinit must execute on a certain queue<br class="gmail_msg">
&gt; (let&#39;s call it q--in my case it is a global queue).  I have a second<br class="gmail_msg">
&gt; class AsyncHandle which owns a Handle and needs to be able to deinit on<br class="gmail_msg">
&gt; any queue.  There&#39;s a tension to resolve between the deinitialization<br class="gmail_msg">
&gt; contracts of Handle and AsyncHandle.  To resolve it, in AsyncHandle&#39;s<br class="gmail_msg">
&gt; deinit, I am binding the owned instance of Handle to a local variable,<br class="gmail_msg">
&gt; dispatching async onto the q, and from the async closure, calling<br class="gmail_msg">
&gt; extendLifetime with the Handle, where extendLifetime is the following:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; @inline(never) func extendLifetime&lt;T : AnyObject&gt;() {}<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; AsyncHandle&#39;s deinit looks like<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; deinit {<br class="gmail_msg">
&gt;     let handle = self.handle<br class="gmail_msg">
&gt;     q.async {<br class="gmail_msg">
&gt;         extendLifetime(handle)<br class="gmail_msg">
&gt;     }<br class="gmail_msg">
&gt; }<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; This approach seems to work--the Handle gets deinit on q, the<br class="gmail_msg">
&gt; appropriate queue.  Most of the time.  In the debugger, there is never a<br class="gmail_msg">
&gt; problem.  Occasionally and inconsistently, on some devices, I am,<br class="gmail_msg">
&gt; however, seeing a behavior that _seems_ to be the synchronous<br class="gmail_msg">
&gt; deallocation of Handle from AsyncHandle&#39;s deinit on the queue that<br class="gmail_msg">
&gt; AsyncHandle happens to be deinitializing on (not q).  If that is indeed,<br class="gmail_msg">
&gt; the behavior I&#39;m seeing, I do not understand why it is happening.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; A few questions:<br class="gmail_msg">
&gt; (1) Given an object B owned (exclusively--no other objects have<br class="gmail_msg">
&gt; references to A) by an object A, is it legal to extend the lifetime of B<br class="gmail_msg">
&gt; in the deinit of A?  (It might conceivably not be legal if there is a<br class="gmail_msg">
&gt; rule such as the following: when the runtime observes that an object R<br class="gmail_msg">
&gt; referenced by a field of a deinitializing object O has a reference count<br class="gmail_msg">
&gt; of one, it assumes that R must die when O dies and consequently puts R<br class="gmail_msg">
&gt; into some moribund state from which there is no revivification.)<br class="gmail_msg">
&gt; (2) If it is legal, is calling extendLifetime from a dispatch async the<br class="gmail_msg">
&gt; appropriate way to do it?<br class="gmail_msg">
&gt; (3) Is my &quot;implementation&quot; (such as it is) of extendLifetime correct?<br class="gmail_msg">
&gt;  (I can&#39;t use the stdlib&#39;s _fixLifetime, unfortunately, or even<br class="gmail_msg">
&gt; implement extendLifetime in the same way.)<br class="gmail_msg">
<br class="gmail_msg">
Have you tried using the standard library&#39;s withExtendedLifetime(_:_:)<br class="gmail_msg">
function?<br class="gmail_msg">
<br class="gmail_msg">
&gt; (4) Does optimization based on visibility enter into this?  In my case<br class="gmail_msg">
&gt; the AsyncHandle is fileprivate.<br class="gmail_msg">
&gt; (5) Is there any entirely different approach to satisfy the following<br class="gmail_msg">
&gt; requirements?  (a) AsyncHandle be releasable/deinitializable on any<br class="gmail_msg">
&gt; thread.  (b) Handle be deinitialized only on some dispatch queue q.  (c)<br class="gmail_msg">
&gt; AsyncHandle has the only reference to Handle.<br class="gmail_msg">
<br class="gmail_msg">
</blockquote></div></div></blockquote></div></div>