This way, if field is null texture is null, otherwise you get texture[0]. You’re right though - if you aren’t used to thinking about concurrency issues (I’m not), it’s confusing.
Actually though, I would’ve thought that a separate thread calling it wouldn’t change what field refers to; it’d be a separate execution “instance”, wouldn’t it?
Actually, ignore the last part of my comment - for some reason I was thinking of field as a parameter (i.e. value instead). Field can definitely get changed by concurrent threads.
(I’m leaving my previous comment instead of editing to remind me to pay a little more attention )
That’s my point exactly but compiler does not know that, somehow. I wonder if this is a bug or am I just missing something here? If field was a dynamic property (which it is not, is it?) there would be a possibility that the returned value changes during the get() call (if(field == null)), but I think it’s supposed to be just a field, as the name and docs suggest.
Hmm, I don’t think that creating a thread safe code should be relevant in this case (if I wanted this method/property to be thread safe, I’d add @Synchronized). I think that what the compiler assumes is that the property can change during its accessor call (which is true, but I’m not accessing the property this way here).
edit: @mplatvoet, I somehow missed the “not” in your previous post
I think I’m missing you’re point then, ergo I don’t understand what you’re saying.
I thought you where saying that in your previous example it was impossible for the value of field in the else branch to be null. That’s the part I reacted to, it can be null if this code is called concurrently. Therefor the compiler can’t/shouldn’t make assumptions about the state of the field.
Hmm, I don’t think that creating a thread safe code should be relevant in this case (if I wanted this method/property to be thread safe, I’d add @Synchronized).
If you make it (provable) threadsafe maybe the compiler could avoid the second null check, though it’s not trivial prove that statically. Even in this case only adding @Synhronized to this overridden property can’t guarantee threadsafety because the super property should be guarded too with the same lock.
A reasonable sound approach for these cases is introducing a local val like so:
override var mesh:MeshDisplay? = null
set(value) {
super.mesh = value
val current = field
if(current == null) {
texture = null
}
else {
texture = current.textures[0]
}
}
Note that this is just an example to satisfy the compiler, not threadsafety.
This isn’t supposed to be thread-safe (and I doubt it’s what the compiler complains about) - it’s about smart casts and that they for some reason don’t work in this scenario. The compiler says it’s not guaranteed field is not null in the else-branch, because it’s a dynamic property that could’ve changed. But it couldn’t!
You’re mentioning concurrency, but does the compiler assume everything has to be thread-safe? I don’t think so (this makes very little sense, because, in general, all code doesn’t have to be thread-safe). And apart from that there are no other ways of changing field’s value - it can only be changed by directly assigning another value to it OR by super.get()/set() call - both of these things aren’t there.
The compiler doesn’t know you’re writing code that doesn’t need to be thread safe; it’s working on trying to ensure that your code is thread safe. All it knows is that your trying to dereference a mutable and nullable field, and it doesn’t like that. If you’re not concerned with thread safety (i.e. you know it’s always going to be non-null in that instance), you can force the dereference like you did with !!. An alternative would be to use the safe access operator - field?.textures[0] - which should do the trick and keep the compiler happy.