Native Threading Obersavtions


#1

Here’s some sample code (updated from original with more readable code)

import konan.worker.*


fun main(args: Array<String>) {
    println("Starting main")

    myWorker.schedule(TransferMode.CHECKED,{UnusedWorkData("yyy")}){
        println("Running worker")
        UnusedWorkData("zzz")
    }
}

val myWorker = startWorker()
val globalOtherClass = GlobalClass()


class GlobalClass{
    init {
        println("GlobalClass init")
    }
}

data class UnusedWorkData(val a:String)

What would you expect the output to be? I’m trying to build a mental model of how threading in native works, but it’s a little confusing. Running this multiple times produces various output.

GlobalClass init
Starting main
GlobalClass init
Running worker
GlobalClass init
GlobalClass init
Starting main
GlobalClass init
Running worker
GlobalClass init
Starting main
GlobalClass init
GlobalClass init
Running worker
GlobalClass init
Starting main
GlobalClass init
GlobalClass initRunning worker

These are all separate runs, using the “Hello World” template sample in CLion as the starting point. They are all presumably running “HelloWorld.kexe” as an independent executable.

The pattern seems variable. I was assuming println itself wasn’t running into thread issues, but the last example, with a print but no newline, implies that might have something to do with it.


#2

Please use “```kotlin” instead of //START SAMPLE

and “```” tags instead of //END SAMPLE

to format code


#3

Some more tests. Updating the code to busy loop and wait, I get some really strange output

import konan.worker.*


fun main(args: Array<String>) {
    println("Starting main")

    val future = myWorker.schedule(TransferMode.CHECKED, { UnusedWorkData("yyy") }) {
        println("Running worker")
        var tempVal = 0
        for(i in 0 .. 300000)
        {
            tempVal = i + 1000
        }
        println("Worker Done")
        UnusedWorkData("zzz")
    }

    future.consume {
        println("future.consume")
    }

    println("end method")
}

val myWorker = startWorker()
val globalOtherClass = GlobalClass()


class GlobalClass{
    constructor() {
        println("GlobalClass constructor")
    }
}

data class UnusedWorkData(val a:String)

The output seems to create a lot of GlobalClass instances. The more loops run, the more instances, although it’s not 1to1 obviously and I’m not sure how linear it is (the number and order aren’t 100% stable).

GlobalClass constructor
Starting main
GlobalClass constructor
Running worker
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
Worker Done
GlobalClass constructor
future.consume
end method

Another example

GlobalClass constructor
GlobalClass constructor
Starting main
Running worker
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
GlobalClass constructor
Worker Done
future.consume
end method
GlobalClass constructor

I’m not sure what it’s doing, but it’s definitely weird.


#4

OK. Never mind. Creating the worker creates a new instance of state, which creates a new worker, which creates another instance of state, repeating till the main process ends apparently. I think that’s what’s happening, anyway. If I move the worker to be local in main, everything runs as expected.