[swift-users] Postponing owned object deinitialization
Nate Chandler
nathaniel.chandler at gmail.com
Mon Feb 27 12:20:19 CST 2017
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 <ole at 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.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20170227/6428a3c6/attachment.html>
More information about the swift-users
mailing list