Is '_ = x' guaranteed to hold a reference to x?


(Michael Ferenduros) #1

I'm doing a RAII sort of thing with an object, and would like to keep it
alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live
reference to the object?

I was told that the optimiser is free to discard this line, and thus the
object could be freed prematurely depending on how the code is compiled. If
so, is there an idiomatic way to do this? Or should I just avoid RAII in
Swift?

Thanks!
Mike Ferenduros


(Joe Groff) #2

`withExtendedLifetime(x) { ... }` is the supported way of extending the lifetime of an object.

-Joe

···

On Jun 30, 2017, at 11:47 AM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?


(Charles Srstka) #3

Nope. In fact, if you try this, you’ll find that it dies immediately after the initializer returns:

class C {
  deinit { print("Deinit!") }
}

do {
  print("Creating")
  _ = C()
  print("Created")
}
print("Left the block”)

- - - - -

Creating
Deinit!
Created
Left the block

Charles

···

On Jun 30, 2017, at 1:47 PM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?


(^) #4

You should probably use `withExtendedLifetime(_:_:slight_smile:
<https://developer.apple.com/documentation/swift/1541033-withextendedlifetime>`
for this.

···

On Fri, Jun 30, 2017 at 2:54 PM, Charles Srstka via swift-users < swift-users@swift.org> wrote:

> On Jun 30, 2017, at 1:47 PM, Mike Ferenduros via swift-users < > swift-users@swift.org> wrote:
>
> I'm doing a RAII sort of thing with an object, and would like to keep it
alive until an completion-block is called (asynchronously).
>
> Is it sufficient to say '_ = x' in the completion-block to keep a live
reference to the object?
>
> I was told that the optimiser is free to discard this line, and thus the
object could be freed prematurely depending on how the code is compiled. If
so, is there an idiomatic way to do this? Or should I just avoid RAII in
Swift?

Nope. In fact, if you try this, you’ll find that it dies immediately after
the initializer returns:

class C {
        deinit { print("Deinit!") }
}

do {
        print("Creating")
        _ = C()
        print("Created")
}
print("Left the block”)

- - - - -

Creating
Deinit!
Created
Left the block

Charles
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


(Michael Ferenduros) #5

With an empty body, you mean?

···

On 30 Jun 2017, at 22:00, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 11:47 AM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?

`withExtendedLifetime(x) { ... }` is the supported way of extending the lifetime of an object.

-Joe


(Joe Groff) #6

With an empty body, you mean?

I'd say it's probably more readable to nest the code that's dependent on the lifetime of the object in the block body, though you can just put `withExtendedLifetime(x) { }` at the end of the region (or `defer { withExtendedLifetime... }` at the beginning) if you can't have the nesting for whatever reason.

-Joe

···

On Jun 30, 2017, at 12:13 PM, Mike Ferenduros <mike.ferenduros@gmail.com> wrote:

On 30 Jun 2017, at 22:00, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 11:47 AM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?

`withExtendedLifetime(x) { ... }` is the supported way of extending the lifetime of an object.

-Joe


(Michael Ferenduros) #7

Ah, I think I was unclear - I want to extend the lifetime into an escaping closure, not just within a scope, and I was wondering what the minimal way is to do that.

···

On 30 Jun 2017, at 22:15, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 12:13 PM, Mike Ferenduros <mike.ferenduros@gmail.com> wrote:

With an empty body, you mean?

I'd say it's probably more readable to nest the code that's dependent on the lifetime of the object in the block body, though you can just put `withExtendedLifetime(x) { }` at the end of the region (or `defer { withExtendedLifetime... }` at the beginning) if you can't have the nesting for whatever reason.

-Joe

On 30 Jun 2017, at 22:00, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 11:47 AM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?

`withExtendedLifetime(x) { ... }` is the supported way of extending the lifetime of an object.

-Joe


(Joe Groff) #8

Ah, I think I was unclear - I want to extend the lifetime into an escaping closure, not just within a scope, and I was wondering what the minimal way is to do that.

I see. Using `withExtendedLifetime` inside the closure still ought to guarantee that the closure captures the variable, and will have the effect of keeping it alive till the closure dies.

-Joe

···

On Jun 30, 2017, at 12:25 PM, Mike Ferenduros <mike.ferenduros@gmail.com> wrote:

On 30 Jun 2017, at 22:15, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 12:13 PM, Mike Ferenduros <mike.ferenduros@gmail.com> wrote:

With an empty body, you mean?

I'd say it's probably more readable to nest the code that's dependent on the lifetime of the object in the block body, though you can just put `withExtendedLifetime(x) { }` at the end of the region (or `defer { withExtendedLifetime... }` at the beginning) if you can't have the nesting for whatever reason.

-Joe

On 30 Jun 2017, at 22:00, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 11:47 AM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?

`withExtendedLifetime(x) { ... }` is the supported way of extending the lifetime of an object.

-Joe


(Michael Ferenduros) #9

Awesome, thanks :slight_smile:

···

On 30 Jun 2017, at 22:27, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 12:25 PM, Mike Ferenduros <mike.ferenduros@gmail.com> wrote:

Ah, I think I was unclear - I want to extend the lifetime into an escaping closure, not just within a scope, and I was wondering what the minimal way is to do that.

I see. Using `withExtendedLifetime` inside the closure still ought to guarantee that the closure captures the variable, and will have the effect of keeping it alive till the closure dies.

-Joe

On 30 Jun 2017, at 22:15, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 12:13 PM, Mike Ferenduros <mike.ferenduros@gmail.com> wrote:

With an empty body, you mean?

I'd say it's probably more readable to nest the code that's dependent on the lifetime of the object in the block body, though you can just put `withExtendedLifetime(x) { }` at the end of the region (or `defer { withExtendedLifetime... }` at the beginning) if you can't have the nesting for whatever reason.

-Joe

On 30 Jun 2017, at 22:00, Joe Groff <jgroff@apple.com> wrote:

On Jun 30, 2017, at 11:47 AM, Mike Ferenduros via swift-users <swift-users@swift.org> wrote:

I'm doing a RAII sort of thing with an object, and would like to keep it alive until an completion-block is called (asynchronously).

Is it sufficient to say '_ = x' in the completion-block to keep a live reference to the object?

I was told that the optimiser is free to discard this line, and thus the object could be freed prematurely depending on how the code is compiled. If so, is there an idiomatic way to do this? Or should I just avoid RAII in Swift?

`withExtendedLifetime(x) { ... }` is the supported way of extending the lifetime of an object.

-Joe