Niklas
11/30/2023, 1:43 PM<http://Dispatchers.IO|Dispatchers.IO>
has on iOS? Is it also backed by a global queue like Dispatchers.Default
which is mentioned here: https://kotlinlang.org/docs/native-migration-guide.html#update-dependencies ? Unfortunately I can’t find any information about this and in the code I only see that the DefaultIoScheduler
is being used for <http://Dispatchers.IO|Dispatchers.IO>
. To be honest, I don’t know exactly what it does.Daniel Pitts
11/30/2023, 5:21 PM<http://Dispatchers.IO|Dispatchers.IO>
. If you don't, you run the risk for blocking threads that are expecting to run in a non-blocking manner.uli
12/01/2023, 8:57 AMNiklas
12/01/2023, 9:17 AM<http://Dispatchers.IO|Dispatchers.IO>
and run the iOS app, everything seems to work fine and it doesn't seem to run on the main thread. But I can't find any information on how this works.uli
12/01/2023, 10:20 AMuli
12/01/2023, 10:24 AMNiklas
12/02/2023, 12:33 PMlaunch(Dispatchers.Main) {
println("Main: $currentThread")
}
launch(Dispatchers.Default) {
println("Default: $currentThread")
}
launch(<http://Dispatchers.IO|Dispatchers.IO>) {
println("IO: $currentThread")
}
launch(newSingleThreadContext("MyOwnThread")) {
println("MyOwnThread: $currentThread")
}
iOS:
IO: <NSThread: 0x2800dd100>{number = 10, name = (null)}
Default: <NSThread: 0x2800d5280>{number = 11, name = (null)}
MyOwnThread: <NSThread: 0x2800b1280>{number = 12, name = (null)}
Main: <_NSMainThread: 0x2800b4040>{number = 1, name = main}
Android:
IO: DefaultDispatcher-worker-5
Default: DefaultDispatcher-worker-5
MyOwnThread: MyOwnThread
Main: main
Seems so that on iOS different background thread are created and on Android these are reused for IO and Default.uli
12/02/2023, 12:59 PMNiklas
12/02/2023, 1:47 PMwithContext
. Apparently it is always executed on the same background thread on iOS for the respective dispatcher and switched on Android if necessary.
withContext(Dispatchers.Default) {
println("Default 1: $currentThread")
}
withContext(Dispatchers.Default) {
println("Default 2: $currentThread")
}
withContext(Dispatchers.IO) {
println("IO 1: $currentThread")
}
withContext(Dispatchers.IO) {
println("IO 2: $currentThread")
}
withContext(Dispatchers.IO) {
println("IO 3: $currentThread")
}
iOS:
Default 1: <NSThread: 0x282b05080>{number = 4, name = (null)}
Default 2: <NSThread: 0x282b05080>{number = 4, name = (null)}
IO 1: <NSThread: 0x282be8280>{number = 9, name = (null)}
IO 2: <NSThread: 0x282be8280>{number = 9, name = (null)}
IO 3: <NSThread: 0x282be8280>{number = 9, name = (null)}
Android:
Default 1: DefaultDispatcher-worker-9
Default 2: DefaultDispatcher-worker-9
IO 1: DefaultDispatcher-worker-9
IO 2: DefaultDispatcher-worker-3
IO 3: DefaultDispatcher-worker-4
Daniel Pitts
12/02/2023, 6:48 PMuli
12/02/2023, 6:51 PMwithContext{Disptachers.Default)
to see how switching between those Dispatchers works.
withContext(Dispatchers.Default) {
withContext(Dispatchers.Default) {
println("Default 1: $currentThread")
}
withContext(Dispatchers.Default) {
println("Default 2: $currentThread")
}
withContext(Dispatchers.IO) {
println("IO 1: $currentThread")
}
withContext(Dispatchers.IO) {
println("IO 2: $currentThread")
}
withContext(Dispatchers.IO) {
println("IO 3: $currentThread")
}
}
Or nest them:
withContext(Dispatchers.Default) {
println("Default 1: $currentThread")
withContext(Dispatchers.Default) {
println("Default 2: $currentThread")
withContext(Dispatchers.IO) {
println("IO 1: $currentThread")
withContext(Dispatchers.IO) {
println("IO 2: $currentThread")
withContext(Dispatchers.IO) {
println("IO 3: $currentThread")
}
}
}
}
}
What’s happening with your test setup is probably, that you switch back to the surrounding dispatchers thread between each withContext.uli
12/02/2023, 6:56 PMuli
12/02/2023, 6:58 PMNiklas
12/03/2023, 1:12 PMasync Default 1: <NSThread: 0x600001708800>{number = 7, name = (null)}
async Default 2: <NSThread: 0x600001708800>{number = 7, name = (null)}
async Default 3: <NSThread: 0x600001708800>{number = 7, name = (null)}
async IO 1: <NSThread: 0x6000017342c0>{number = 8, name = (null)}
async IO 2: <NSThread: 0x6000017342c0>{number = 8, name = (null)}
async IO 3: <NSThread: 0x6000017342c0>{number = 8, name = (null)}
@uli The same applies here. Different threads are created for Default and IO, but these are reused for the respective dispatcher. On android it behaves like you said. There are no context switches. And my tests are running inside runBlocking.
iOS:
withContext wrapped in Default: <NSThread: 0x600001703140>{number = 6, name = (null)}
withContext wrapped Default 1: <NSThread: 0x600001703140>{number = 6, name = (null)}
withContext wrapped Default 2: <NSThread: 0x600001703140>{number = 6, name = (null)}
withContext wrapped IO 1: <NSThread: 0x60000176d1c0>{number = 8, name = (null)}
withContext wrapped IO 2: <NSThread: 0x60000176d1c0>{number = 8, name = (null)}
withContext wrapped IO 3: <NSThread: 0x60000176d1c0>{number = 8, name = (null)}
--------
withContext nested Default 1: <NSThread: 0x600001703140>{number = 6, name = (null)}
withContext nested Default 2: <NSThread: 0x600001703140>{number = 6, name = (null)}
withContext nested IO 1: <NSThread: 0x60000176d1c0>{number = 8, name = (null)}
withContext nested IO 2: <NSThread: 0x60000176d1c0>{number = 8, name = (null)}
withContext nested IO 3: <NSThread: 0x60000176d1c0>{number = 8, name = (null)}
Android:
withContext wrapped in Default: DefaultDispatcher-worker-2
withContext wrapped Default 1: DefaultDispatcher-worker-2
withContext wrapped Default 2: DefaultDispatcher-worker-2
withContext wrapped IO 1: DefaultDispatcher-worker-2
withContext wrapped IO 2: DefaultDispatcher-worker-2
withContext wrapped IO 3: DefaultDispatcher-worker-2
--------
withContext nested Default 1: DefaultDispatcher-worker-5
withContext nested Default 2: DefaultDispatcher-worker-5
withContext nested IO 1: DefaultDispatcher-worker-5
withContext nested IO 2: DefaultDispatcher-worker-5
withContext nested IO 3: DefaultDispatcher-worker-5
uli
12/03/2023, 1:15 PMNiklas
12/03/2023, 1:22 PM