Jason Zhao
07/23/2023, 7:46 AM<http://Dispatchers.IO|Dispatchers.IO>
everywhere you would normally use Dispatchers.Default
?
Of course, normally doing this would have no benefit (but likely no drawbacks either?) other than making sure that you no longer need to care about the distinction between IO
and Main
dispatchers. However, doing this would also allow combining blocking with non-blocking operations to do some pretty unique and cool stuff, essentially using suspends as a way to explicitly switch context.
For example I can use a coroutine context with limitedParallelism(1)
to encompass some resource (e.g. a Player in a game project) that contains a lot of data and logic. This data is all non-synchronized in order to make it more maintainable and have less overhead (think a Node.JS event loop).
So, if I use a Loom IO dispatcher, I think I shouldn't be afraid of blocking the coroutine at all. If during the logic, I need to wait for something but don't want the data in my object to change from other coroutines while I wait, then I can choose to block (e.g. via runBlocking
). If I need to wait but don't mind the data changing in the process, then I can choose to suspend, and let other coroutines run on my limitedParallelism
context. So I can always get the best level of concurrency depending on what behavior I expect in my code.Sam
07/23/2023, 8:44 AMRiccardo Lippolis
07/23/2023, 1:14 PMJason Zhao
07/24/2023, 12:24 AMRiccardo Lippolis
07/24/2023, 5:53 AMDispatchers.Default
to a Dispatcher using Virtual Threads would always involve a thread context switch.
If you'd just run all coroutines on a Virtual Thread dispatcher, the dispatcher would just spawn a new Virtual Thread for every coroutine started (because the dispatcher schedules it using an Executor that just creates a new one for each task that gets submitted), and the coroutine might or might not run fully on a single carrier thread, probably depending on whether it will actually suspend (but the key thing here is: you shouldn't depend on it 😅)