[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