I'm trying to understand asynchronous computation by cats.effect.IO
examples and got some misunderstanding. The unsafe
method unsafeRunAsync
seems like running the underlying effect asynchronously (I expected that some ContextShift
to be provided). But the method looks simply like this:
final def unsafeRunAsync(cb: Either[Throwable, A] => Unit): Unit =
IORunLoop.start(this, cb)
Neither ContextShift
nor ExecutionContext
is provided. Here is the very simple example:
object TestIo extends App {
println(s"Main thread = ${Thread.currentThread().getName}")
val io = IO {
println(s"Effect thread = ${Thread.currentThread().getName}")
Thread.sleep(1000)
}
io.unsafeRunAsync(_ => println(s"Callback thread = ${Thread.currentThread().getName}"))
println(s"Finished")
}
The output is
Main thread = main
Effect thread = main
Callback thread = main
Finished
As you can see everything here is run in the main thread synchronously. Can you please explain unsafeRunAsync
? To me it seems the same as unsafeRunSync
.
About
Neither ContextShift nor ExecutionContext is provided.
There is a context switch in cats.effect.IO
See this blog: https://www.jaspervanzandbeek.com/scala/cats-io-monad/
Here an example from there:
def blockingOperation(): String = {
// Read from file
...
}
val result: IO[String] = for {
_ <- IO.shift(executionContextForBlockingOperations)
result <- IO { blockingOperation() }
_ <- IO.shift(mainExecutionContext)
} yield result