> On Sep 21, 2016, at 3:14 PM, Xiaodi Wu via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> I haven't used it myself, but is this the use case addressed by 
> `withExtendedLifetime(_:_:)`?

Yeah, if you want to vend resources managed by an object to consumers outside 
of that object like this, you need to use withExtendedLifetime to keep the 
object alive for as long as you're using the resources. A cleaner way to model 
this might be to put the class or protocol in control of handling the I/O to 
the file handle, instead of vending the file handle itself, so that the 
ownership semantics fall out more naturally:

protocol Storage {
  func write(bytes: UnsafeRawPointer, count: Int)
}

func save(string: String, to: Storage?) {
    if let data = string.data(using: String.Encoding.utf8) {
        data.withUnsafeBytes {
            _ = to?.write(bytes: $0, count: data.count)
        }
    }
}

-Joe

> On Wed, Sep 21, 2016 at 16:54 John Holdsworth via swift-evolution 
> <swift-evolution@swift.org> wrote:
> Hi,
> 
> For complex statements in C++ any temporary instances created in the course
> of an expression have their lifetime extended to the completion of the current
> statement after which they are all deallocated en masse. This makes certain
> types of language usage possible and easier to reason with.
> 
> I’m bringing this up as I had a problem with some code crashing only when
> compiled with release configuration and the problem could have been avoided
> if Swift deferred deallocation to the end of a statement. While Swift’s ARC 
> policy
> is consistent in itself this seems to be a particular problem interfacing 
> between
> language/reference counting systems. My problem code was a Java-Swift Bridge.
> 
> A contrived example:
> 
> import Foundation
> 
> protocol Storage {
>     var fp: UnsafeMutablePointer<FILE> { get }
> }
> 
> class FileStorage: Storage {
> 
>     let fp: UnsafeMutablePointer<FILE>
> 
>     init?(path: String, mode: String = "w") {
>         print("Opening")
>         let fp = fopen(path, mode)
>         if fp == nil {
>             return nil
>         }
>         self.fp = fp!
>     }
> 
>     deinit {
>         print("Closing")
>         fclose(fp)
>     }
> }
> 
> func save(string: String, to: Storage?) {
>     if let data = string.data(using: String.Encoding.utf8) {
>         print("Saving1")
>         if let fp = to?.fp {
>             print("Saving2")
>             data.withUnsafeBytes {
>                 _ = fwrite($0, 1, data.count, fp)
>             }
>             print("Saving3")
>         }
>     }
> }
> 
> save(string: "Hello World\n", to: FileStorage(path: "/tmp/a.txt"))
> 
> 
> In debug configuration is prints:
> Opening
> Saving1
> Saving2
> Saving3
> Closing
> 
> Whereas in release configuration it prints:
> Opening
> Saving1
> Closing <!!!
> Saving2
> Saving3
> 
> The optimiser is vigorously deallocating objects when they are no longer 
> referenced regardless
> of whether an variable referencing it is still in scope (In fairness this 
> particular problem only occurs
> for Optional augments of Protocols) but this behaviour seems to be implicit 
> in the current language
> spec. The alternative is to retain arguments themselves as I believe they are 
> in Objective-C ARC.
> 
> This would have been avoided if the temporary FileStorage instance has been 
> considered to have
> a lifetime up to the end of the statement calling function save() and hence 
> the duration of the call.
> This needed increase ARC overhead in any way. Just alter the timing of it to 
> be more conservative.
> 
> John
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

Reply via email to