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

Michael Henson mikehenson at gmail.com
Mon Dec 14 22:19:10 CST 2015


Something occurred to me while I was thinking through a response to the
thread issue. The language already provides a couple of things that behave
similarly:

* deinit methods
* property setters

I couldn't find a documented guarantee for either of them to run on a
particular thread, or any explicit detail on guarantees of behavior in
threaded environments.

Given that every weak reference has to be an Optional type, I ran the
following test code to see if setters are called when a weak reference
becomes nil:

// swift-2.2-SNAPSHOT-2015-12-10-a-ubuntu15.10
import Glibc

class Beeper {
  func beep() {
    print("Beep")
  }
}

class Holder {
  weak var beeper: Beeper? {
    willSet {
      print("willSet: \(newValue)")
    }
    didSet {
      print("didSet: \(beeper)")
    }
  }

  func doExampleLogic() {
    // so there was, at one time, a strong reference in this context
    let beeper = Beeper()
    self.beeper = beeper
  }
}

let holder = Holder()
holder.doExampleLogic()

for i in 0..<15 {
  print("\(i):")

  if let heldBeeper = holder.beeper {
    print("held beeper exists")
  } else {
    print("held beeper is nil")
  }
}

Results:
$ swift beeper.swift
willSet: Optional(beeper.Beeper)
didSet: Optional(beeper.Beeper)
0:
held beeper exists
1:
held beeper exists
2:
held beeper exists
3:
held beeper exists
4:
held beeper exists
5:
held beeper exists
6:
held beeper exists
7:
held beeper exists
8:
held beeper exists
9:
held beeper exists
10:
held beeper exists
11:
held beeper exists
12:
held beeper exists
13:
held beeper exists
14:
held beeper exists

I see the exact same results if I compile with swiftc. I expected the
weakened optional to set itself to nil when the strong reference went out
of scope at the end of doExampleLogic(). Have I misunderstood how weakening
works?

Mike


On Mon, Dec 14, 2015 at 1:06 PM, Greg Parker <gparker at apple.com> 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
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151214/88d23114/attachment.html>


More information about the swift-evolution mailing list