Non Blocking Channel Operations in Kotlin
Basic sends and receives on channels are blocking. However, we can use select
with a default
clause to implement non-blocking sends, receives, and even non-blocking multi-way select
s.
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.selects.*
fun main() = runBlocking {
val messages = Channel<String>()
val signals = Channel<Boolean>()
// Here's a non-blocking receive. If a value is
// available on `messages` then `select` will take
// the `messages.onReceive` case with that value. If not
// it will immediately take the `onDefault` case.
select<Unit> {
messages.onReceive { msg ->
println("received message $msg")
}
onDefault {
println("no message received")
}
}
// A non-blocking send works similarly. Here `msg`
// cannot be sent to the `messages` channel, because
// the channel has no buffer and there is no receiver.
// Therefore the `onDefault` case is selected.
val msg = "hi"
select<Unit> {
messages.onSend(msg) {
println("sent message $msg")
}
onDefault {
println("no message sent")
}
}
// We can use multiple cases above the `onDefault`
// clause to implement a multi-way non-blocking
// select. Here we attempt non-blocking receives
// on both `messages` and `signals`.
select<Unit> {
messages.onReceive { msg ->
println("received message $msg")
}
signals.onReceive { sig ->
println("received signal $sig")
}
onDefault {
println("no activity")
}
}
}
To run the program:
$ kotlinc non-blocking-channel-operations.kt -include-runtime -d non-blocking-channel-operations.jar
$ java -jar non-blocking-channel-operations.jar
no message received
no message sent
no activity
In this Kotlin version, we’re using coroutines and channels to replicate the behavior of Go’s channels and select statements. The select
function from the kotlinx.coroutines.selects
package provides similar functionality to Go’s select
statement.
Note that unlike Go, Kotlin’s channels are not built into the language and require the kotlinx.coroutines
library. Also, the syntax for channel operations is slightly different, using methods like onReceive
and onSend
instead of the arrow operators used in Go.
The overall structure and behavior of the program remain the same, demonstrating non-blocking channel operations in Kotlin.