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