Constructor is always executed when using atomic.compareAndSet()

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!

I know the feeling :stuck_out_tongue_winking_eye: