[swift-evolution] Proposal: Give weak references the ability to notify reference-holders when they transition to nil

Etan Kissling kissling at oberon.ch
Tue Dec 15 12:23:31 CST 2015


The first case where `willDeinit` is not allowed to resurrect the object is probably not really usable.

Code needs to be able to assume that claiming a weakly referenced object is something nonblocking.

This can only be the case if `willDeinit` completes in a timely fashion - probably still too much if you need to call user code.
If it's fast enough, I would strongly suggest some wording like `unsafeWillDeinit` to emphasize that.



In the end, that leaves the `willTryToDeinit` / `didDeinit` concept.

`didDeinit` is essentially the same that we have now, when we post a notification at the end of `deinit`
that contains an identifier of the deallocated object to be removed from dictionaries etc.

`willTryToDeinit` is something invoked when all strong references are removed from the object,
and may be called multiple times if another thread concurrently claims a strong reference to the object,
or if one of the callbacks decides to resurrect the object past its runtime.

Etan



> On 15 Dec 2015, at 19:10, Etan Kissling <kissling at oberon.ch> wrote:
> 
> Why not both?
> 
> Allow synchronous callbacks for people who know what they do
> (writing a global exception handler in other languages can also create major issues if you do it the wrong way)
> and allow asynchronous callbacks for people who just want to clean up their collection eventually.
> 
> 
> Maybe an approach with `willDeinit` and `didDeinit` would be great here, mirroring the already existing `willSet` and `didSet`.
> 
> 1. Last strong reference removed
> 2. All `willDeinit` observers are invoked. It is illegal to resurrect an object in these callbacks.
> 3. All weak references are zeroed.
> 4. All `didDeinit` observers are invoked, potentially asynchronously.
> 
> The `willDeinit` cannot be merged with the `willSet` because of the additional non-resurrection constraints.
> The `didDeinit` could be merged with the `didSet`. Although a `didSet` without a preceding `willSet` is kind of strange.
> 
> 
> Property would look like this:
> 
> weak var x: T? {
>    willSet {
>        // Not called on automatic zeroing.
>    }
>    didSet {
>        // Not called on automatic zeroing.
>    }
>    willDeinit {
>        // Object is dying.
>    }
>    didDeinit {
>        // Object has died sometime ago.
>    }
> }
> 
> 
> 
> Alternatively, allow object resurrection between the removal of the last strong reference and the completion of all `willDeinit` callbacks.
> `willDeinit` becomes advisory in this case, and may be called multiple times. Maybe `willTryToDeinit` would be clearer in the meaning.
> Only if all `willTryToDeinit` callbacks completed and the object is not resurrected, the references are zeroed and `didDeinit` callbacks are called.
> 
> This way, the developer doesn't need to care about special restrictions that apply to `willDeinit`.
> 
> 
> 
> Maybe `unsafeWillDeinit` would be an okay name if you go with the restricted `willDeinit` to scare novices away from that area (similar to pointers).
> 
> 
> Etan
> 
> 
> 
> 
> 
>> On 14 Dec 2015, at 22:06, Greg Parker via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> 
>>> On Dec 13, 2015, at 6:24 PM, Michael Henson via swift-evolution <swift-evolution at swift.org> wrote:
>>> 
>>> The use-case for this comes first from proposals to have a weak-reference version of collection types. Implementing a notification signal of some sort to weak reference-holders when the reference becomes nil would make implementing those more straightforward.
>> 
>> How do you want this to work in the presence of threads?
>> 
>> One option is that the nil transition and the callbacks are performed together, synchronously and atomically with respect to some things. The problem with this scheme is that the callback is limited in what it can do. If it does the wrong thing it will deadlock. The definition of "wrong thing" depends in part on the definition of "atomically with respect to some things". For example, if the callbacks are called atomically with respect to other weak reference writes then the callback must not store to any weak references of its own.
>> 
>> Another option is that the callbacks are performed asynchronously some time after the nil transition itself. (Java's PhantomReference offers something like this.) The problem with this scheme is that the state of the world has moved on by the time the callback is called, which can make the callback difficult to write. In particular there is no guarantee that the weak variable's storage still exists when the callback for that weak variable is executed.
>> 
>> 
>> --
>> Greg Parker     gparker at apple.com     Runtime Wrangler
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151215/8e034735/attachment.sig>


More information about the swift-evolution mailing list