7

Is there any way to check an unowned(safe) Swift reference for "availability"? So, I am looking for a hypothetical function like isReferenceAccessible in this example:

func someMethod() {
  someAsyncOperation(parameters) { [unowned(safe) self] in 
    guard isReferenceAccessible(self) else {
      return
    }

    self.someAnotherMethod()
  }
}

Disclaimer: This question not about weak references! I am aware of how strong, unowned and weak references work. And I don't want to use weak references (because it can be slow, and mutable). I know that unowned(safe) references still be allocated even if it is already deinited when we are trying to access it. And I know that a compiler can do this check and it actually check it before an application is crashed.

So, I believe it can be very powerful and well-performed technic/paradigm for breaking reference cycles in modern Swift.

Moreover, I believe it can be an awesome language feature! For instance, let's assume that we have the modifier called shared_ownership and it works thought above described behaviour like this:

method(parameters) { [shared_ownership self] in
  self.someAnotherMethod()
}

... with implementation like this:

method(parameters) { [unowned(safe) self] in
  guard isReferenceAccessible(self) else {
    return
  }

  self.someAnotherMethod()
}

... with side effects (without weak-related complexity and perfomance penalty) equivalent to:

method(parameters) { [weak self] in
  guard let strongSelf = self else {
    return
  }

  strongSelf.someAnotherMethod()
}

Oh, it would be fantastic!

More info about the differences between weak, unowned(safe), and unowned(unsafe).

Update

I have found awesome Swift proposal that related the feature discussed above: Allow using optional binding to upgrade self from a weak to strong reference.

Community
  • 1
  • 1
Valentin Shergin
  • 7,166
  • 2
  • 50
  • 53
  • 5
    If you think you need to make this check, then you should be using `weak`. – nhgrif Jan 17 '16 at 20:26
  • From a conceptual point of view... probably, yes. But let's assume that I can't use a `weak` reference because of some problem `X`. The `weak` modifier is great, but it is another story. – Valentin Shergin Jan 17 '16 at 20:32
  • 1
    Your usage here has a significant race condition. The object can deinit between the time `isReferenceAccessible` is called and `someAnotherMethod` is called unless you can prove that this object is only ever accessed on a single thread. That seems a very narrow use case. Have you encountered a case where `weak` is causing you a performance problem, all use of this object is on a single thread, but you don't know the lifetime of `self` compared to the block? (That's the only case I can imagine this being helpful.) To make it thread-safe, you'd just recreate `weak`. – Rob Napier Jan 17 '16 at 21:44
  • 1
    (Basically, if what you're saying could be done with much less performance penalty, then that would be how `weak` was implemented.) – Rob Napier Jan 17 '16 at 21:45
  • That referenced dev forum thread concludes with a discussion of the intent of `unowned(safe)`, namely, to ensure that you "get a predictable runtime crash." It's akin to zombies. You can say you don't want `weak`, but frankly it seems that this is exactly what you want, but just don't want to pay the piper. – Rob Jan 17 '16 at 22:11
  • Yes and no. I agree that we have to deal with threading-related issues here, but that is not deal breaker at all (we can fix it any conventional way). (And single-thread usage is definitely not a "narrow case".) I agree that base intent behind `unowned(safe)` was "predictable crash". But my question is not "How to reach this behaviour?", my question is "How to use this particular technical way to reach this behaviour (without using `weak`)?". And, yes, I don't want to pay for `weak` because `weak` (as I know) is implemented another way. – Valentin Shergin Jan 17 '16 at 22:39
  • I don't understand this question any more...so let me try understanding. You want the behavior of `weak` but with better performance? Have you demonstrated that `weak` is too slow in some scenario? – nhgrif Jan 18 '16 at 14:32
  • As I mentioned in my answer, I was wrong, `weak` references in Swift actually as fast as `unowned` one. You are right, I have to use `weak`... or wait for the new language feature that I described. ) Thank you! – Valentin Shergin Jan 18 '16 at 20:08

1 Answers1

8

Suddenly I have found that my original base assumption that weak reference in Swift can be slow is wrong. As we can see from sources, Swift is actually using almost same implementation for weak and unowned references. So weak reference is almost as fast as unowned reference.

(But Objective-C is completely different story, it is using sidetable with tracking of all pointers to week references and deinit, deallocate, and zeroing as one step. And it can be slow.)

And because of this, my questions makes no sense. I have to use week reference and unwrap it as I proposed it in the last piece of code in my original question.

Update: Here is an awesome article by incredible Mike Ash that describes how weak and unowned references work under the hood in Swift.

Valentin Shergin
  • 7,166
  • 2
  • 50
  • 53