[swift-evolution] Should Swift apply "statement scope" for ARC

Joe Groff jgroff at apple.com
Wed Sep 21 18:08:46 CDT 2016


> On Sep 21, 2016, at 4:01 PM, John Holdsworth <mac at johnholdsworth.com> wrote:
> 
> My contrived example was a bit flimsy. I’d better unpack the full story. The real
> code I had problems with was based around the following Java instance wrapper:
> 
> open class JNIObject: JNIObjectProtocol {
> 
>     var _javaObject: jobject?
> 
>     open var javaObject: jobject? {
>         get {
>             return _javaObject
>         }
>         set(newValue) {
>             if newValue != _javaObject {
>                 let oldValue = _javaObject
>                 if newValue != nil {
>                     _javaObject = JNI.api.NewGlobalRef( JNI.env, newValue )
>                 }
>                 else {
>                     _javaObject = nil
>                 }
>                 if oldValue != nil {
>                     JNI.api.DeleteGlobalRef( JNI.env, oldValue )
>                 }
>             }
>         }
>     }
> 
>     deinit {
>         javaObject = nil
>     }
> 
> As a result the following transfer of a Java instance always worked:
> 
>     init(imageProducer:ImageProducer) {
>         let supr = CanvasBase()
>         super.init( javaObject: supr.javaObject )
>         image = createImage(imageProducer)
>     }
> 
> But the following only worked for debug compiles:
> 
>     init(imageProducer:ImageProducer) {
>         super.init( javaObject: CanvasBase().javaObject )
>         image = createImage(imageProducer)
>     }
> 
> Felt like a bit of a bear trap is all. Statement scope would avoid problems like this.

True, though statement scope is also a pretty massive barrier that would prevent important optimizations that are valid for most classes. You might be able to avoid the bear trap by changing the `javaObject` interface into a callback-based interface, that ensures the object remains alive while you have access to it. Instead of:

protocol JNIObjectProtocol {
  var javaObject: jobject { get }
}

would it work to have something like this?

protocol JNIObjectProtocol {
  func withJavaObject(_ body: (jobject) -> ())
}

-Joe


More information about the swift-evolution mailing list