<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Sep 21, 2016, at 4:01 PM, John Holdsworth via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">My contrived example was a bit flimsy. I’d better unpack the full story. The real</div><div class="">code I had problems with was based around the following Java instance wrapper:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">open</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">class</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> JNIObject: </span><span style="font-variant-ligatures: no-common-ligatures" class="">JNIObjectProtocol</span><span style="font-variant-ligatures: no-common-ligatures;" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> _javaObject: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">jobject</span><span style="font-variant-ligatures: no-common-ligatures" class="">?</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">open</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">var</span><span style="font-variant-ligatures: no-common-ligatures" class=""> javaObject: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">jobject</span><span style="font-variant-ligatures: no-common-ligatures" class="">? {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">get</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> _javaObject</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">set</span><span style="font-variant-ligatures: no-common-ligatures" class="">(newValue) {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> newValue != _javaObject {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> oldValue = _javaObject</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> newValue != </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> _javaObject = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">JNI</span><span style="font-variant-ligatures: no-common-ligatures" class="">.api.NewGlobalRef( </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">JNI</span><span style="font-variant-ligatures: no-common-ligatures" class="">.env, newValue )</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> _javaObject = </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> oldValue != </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">JNI</span><span style="font-variant-ligatures: no-common-ligatures" class="">.api.DeleteGlobalRef( </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">JNI</span><span style="font-variant-ligatures: no-common-ligatures" class="">.env, oldValue )</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">deinit</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> javaObject = </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">nil</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div></div><div class="">As a result the following transfer of a Java instance always worked:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(imageProducer:</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ImageProducer</span><span style="font-variant-ligatures: no-common-ligatures" class="">) {</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> supr = CanvasBase()</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">super</span><span style="font-variant-ligatures: no-common-ligatures" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">( javaObject: supr.javaObject )</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> image = createImage(imageProducer)</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div></div></div></div><div class="">But the following only worked for debug compiles:</div><div class=""><br class=""></div><div class=""><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">(imageProducer:</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">ImageProducer</span><span style="font-variant-ligatures: no-common-ligatures" class="">) {</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">super</span><span style="font-variant-ligatures: no-common-ligatures" class="">.</span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">init</span><span style="font-variant-ligatures: no-common-ligatures" class="">( javaObject: CanvasBase().javaObject )</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> image = createImage(imageProducer)</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> }</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div></div></div></div></div><div class="">Felt like a bit of a bear trap is all. Statement scope would avoid problems like this.</div></div></div></blockquote><div><br class=""></div><div>You are thinking about this the inverse way. That the first case works is an artifact of the optimizer failing to do a good enough job. Future improved ARC optimization can cause both to fail.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">John</div><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 21 Sep 2016, at 23:34, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><br class=""><blockquote type="cite" class="">On Sep 21, 2016, at 3:14 PM, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class=""><br class="">I haven't used it myself, but is this the use case addressed by `withExtendedLifetime(_:_:)`?<br class=""></blockquote><br class="">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:<br class=""><br class="">protocol Storage {<br class=""> func write(bytes: UnsafeRawPointer, count: Int)<br class="">}<br class=""><br class="">func save(string: String, to: Storage?) {<br class=""> if let data = string.data(using: String.Encoding.utf8) {<br class=""> data.withUnsafeBytes {<br class=""> _ = to?.write(bytes: $0, count: data.count)<br class=""> }<br class=""> }<br class="">}<br class=""><br class="">-Joe<br class=""><br class=""><blockquote type="cite" class="">On Wed, Sep 21, 2016 at 16:54 John Holdsworth via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class="">Hi,<br class=""><br class="">For complex statements in C++ any temporary instances created in the course<br class="">of an expression have their lifetime extended to the completion of the current<br class="">statement after which they are all deallocated en masse. This makes certain<br class="">types of language usage possible and easier to reason with.<br class=""><br class="">I’m bringing this up as I had a problem with some code crashing only when<br class="">compiled with release configuration and the problem could have been avoided<br class="">if Swift deferred deallocation to the end of a statement. While Swift’s ARC policy<br class="">is consistent in itself this seems to be a particular problem interfacing between<br class="">language/reference counting systems. My problem code was a Java-Swift Bridge.<br class=""><br class="">A contrived example:<br class=""><br class="">import Foundation<br class=""><br class="">protocol Storage {<br class=""> var fp: UnsafeMutablePointer<FILE> { get }<br class="">}<br class=""><br class="">class FileStorage: Storage {<br class=""><br class=""> let fp: UnsafeMutablePointer<FILE><br class=""><br class=""> init?(path: String, mode: String = "w") {<br class=""> print("Opening")<br class=""> let fp = fopen(path, mode)<br class=""> if fp == nil {<br class=""> return nil<br class=""> }<br class=""> self.fp = fp!<br class=""> }<br class=""><br class=""> deinit {<br class=""> print("Closing")<br class=""> fclose(fp)<br class=""> }<br class="">}<br class=""><br class="">func save(string: String, to: Storage?) {<br class=""> if let data = string.data(using: String.Encoding.utf8) {<br class=""> print("Saving1")<br class=""> if let fp = to?.fp {<br class=""> print("Saving2")<br class=""> data.withUnsafeBytes {<br class=""> _ = fwrite($0, 1, data.count, fp)<br class=""> }<br class=""> print("Saving3")<br class=""> }<br class=""> }<br class="">}<br class=""><br class="">save(string: "Hello World\n", to: FileStorage(path: "/tmp/a.txt"))<br class=""><br class=""><br class="">In debug configuration is prints:<br class="">Opening<br class="">Saving1<br class="">Saving2<br class="">Saving3<br class="">Closing<br class=""><br class="">Whereas in release configuration it prints:<br class="">Opening<br class="">Saving1<br class="">Closing <!!!<br class="">Saving2<br class="">Saving3<br class=""><br class="">The optimiser is vigorously deallocating objects when they are no longer referenced regardless<br class="">of whether an variable referencing it is still in scope (In fairness this particular problem only occurs<br class="">for Optional augments of Protocols) but this behaviour seems to be implicit in the current language<br class="">spec. The alternative is to retain arguments themselves as I believe they are in Objective-C ARC.<br class=""><br class="">This would have been avoided if the temporary FileStorage instance has been considered to have<br class="">a lifetime up to the end of the statement calling function save() and hence the duration of the call.<br class="">This needed increase ARC overhead in any way. Just alter the timing of it to be more conservative.<br class=""><br class="">John<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class="">swift-evolution@swift.org<br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class=""></div></div></blockquote></div><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>