Hi everyone
I ran across a strange behavior while using the library kotlinx.atomicfu and I wanted to check if it is a wanted behaviour before filling an issue on github.
Consider the following code
MyClass{
init{
println("constructor called")
}
}
main(){
val atomic : AtomicRef<MyClass?> = atomic(null)
atomic.compareAndSet(null,MyClass())
atomic.compareAndSet(null,MyClass())
}
If we execute that code the output will be
constructor called
constructor called
I was quite surprised when I discover that behavior. I tested it on Kotlin/Native and Kotlin/JVM with the latest version of atomicfu.
The documentation state that the statements passed to atomicfu methods must be simple, is calling a constructor considered a complex statement? Is there a way to atomically set the variable while calling the constructor once using only atomicfu?
Thank you for your help
Yes, this is expected behavior. The reason for this is simple.
Let’s say we have this simple code
class MyClass
fun getMyClass() = MyClass() // probably much more complicated
fun foo(a: MyClass, b: MyClass) = ... // do something
foo(getMyClass(), MyClass())
If you take a closer look at what happens when you call foo
, it’s this
val temp1 = getMyClass()
val temp2 = MyClass()
foo(temp1, temp2)
As you see, you always first compute all arguments and only then call the function. That’s why the constructor is called in both cases in your example. However you will see that atomic will only be changed the first time.
You can check this easy enough with something like this
class MyClass(val i: Int) {
init {
println("constructor called with $i")
}
}
fun main() {
val atomic = atomic(null)
atomic.compareAndSet(null, MyClass(0))
atomic.compareAndSet(null, MyClass(1))
println(atomic.value.i)
}
The output should look like this
constructor called with 0
constructor called with 1
0
1 Like
that moment when your problem is basic programming 101. Thank you very much I think I have been staring at my code for way too long!