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 selects.

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.